[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang Acked-by: Andy king Acked-by: Dmitry Torokhov --- net/vmw_vsock/notify.c | 675 net/vmw_vsock/notify.h | 124 + 2 files changed, 799 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..23bad8b --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,675 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +#include "notify.h" +#include "af_vsock.h" + +#define PKT_FIELD(vsk, field_name) ((vsk)->notify.pkt.field_name) + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +static bool vsock_vmci_notify_waiting_write(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) < + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space > ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window > bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +static bool vsock_vmci_notify_waiting_read(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + if (!PKT_FIELD(vsk, peer_waiting_read)) + return false; + + /* For now we ignore the wait information and just see if there is any +* data for our peer to read. Note that improving this function to be +* more intelligent will not require a protocol change and will retain +* compatibility between endpoints with mixed versions of this +* function. +*/ + return vmci_qpair_produce_buf_ready(vsk->qpair) > 0; +#else + return true; +#endif +} + +static void +vsock_vmci_handle_waiting_read(struct sock *sk, + struct vsock_packet
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang georgezh...@vmware.com Acked-by: Andy king ack...@vmware.com Acked-by: Dmitry Torokhov d...@vmware.com --- net/vmw_vsock/notify.c | 675 net/vmw_vsock/notify.h | 124 + 2 files changed, 799 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..23bad8b --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,675 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include linux/types.h +#include linux/socket.h +#include linux/stddef.h +#include net/sock.h + +#include notify.h +#include af_vsock.h + +#define PKT_FIELD(vsk, field_name) ((vsk)-notify.pkt.field_name) + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +static bool vsock_vmci_notify_waiting_write(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk-consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk-qpair) notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +static bool vsock_vmci_notify_waiting_read(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + if (!PKT_FIELD(vsk, peer_waiting_read)) + return false; + + /* For now we ignore the wait information and just see if there is any +* data for our peer to read. Note that improving this function to be +* more intelligent will not require a protocol change and will retain +* compatibility between endpoints with mixed versions of this +* function. +*/ + return vmci_qpair_produce_buf_ready(vsk-qpair) 0; +#else + return true; +#endif +} + +static void
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang Signed-off-by: Dmitry Torokhov Signed-off-by: Andy King --- net/vmw_vsock/notify.c | 983 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1113 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..8504e28 --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,983 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include + +#include +#include /* for NULL */ +#include + +#include "notify.h" +#include "af_vsock.h" + +#define PKT_FIELD(vsk, field_name) ((vsk)->notify.pkt.field_name) + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) < + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space > ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window > bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + if
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang georgezh...@vmware.com Signed-off-by: Dmitry Torokhov d...@vmware.com Signed-off-by: Andy King ack...@vmware.com --- net/vmw_vsock/notify.c | 983 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1113 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..8504e28 --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,983 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include linux/types.h + +#include linux/socket.h +#include linux/stddef.h /* for NULL */ +#include net/sock.h + +#include notify.h +#include af_vsock.h + +#define PKT_FIELD(vsk, field_name) ((vsk)-notify.pkt.field_name) + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(struct vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk-consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk-qpair) notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang --- net/vmw_vsock/notify.c | 984 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1114 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..5c69c7c --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,984 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include + +#include +#include /* for NULL */ +#include + +#include "notify.h" +#include "af_vsock.h" + +#define PKT_FIELD(vsk, field_name) \ + (vsk)->notify.pkt.field_name + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) < + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space > ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window > bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + if (!PKT_FIELD(vsk, peer_waiting_read)) +
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang georgezh...@vmware.com --- net/vmw_vsock/notify.c | 984 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1114 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..5c69c7c --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,984 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include linux/types.h + +#include linux/socket.h +#include linux/stddef.h /* for NULL */ +#include net/sock.h + +#include notify.h +#include af_vsock.h + +#define PKT_FIELD(vsk, field_name) \ + (vsk)-notify.pkt.field_name + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk-consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk-qpair) notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) +
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang --- net/vmw_vsock/notify.c | 984 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1114 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..5c69c7c --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,984 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include + +#include +#include /* for NULL */ +#include + +#include "notify.h" +#include "af_vsock.h" + +#define PKT_FIELD(vsk, field_name) \ + (vsk)->notify.pkt.field_name + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) < + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space > ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window > bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + if (!PKT_FIELD(vsk, peer_waiting_read)) +
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang georgezh...@vmware.com --- net/vmw_vsock/notify.c | 984 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1114 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..5c69c7c --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,984 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include linux/types.h + +#include linux/socket.h +#include linux/stddef.h /* for NULL */ +#include net/sock.h + +#include notify.h +#include af_vsock.h + +#define PKT_FIELD(vsk, field_name) \ + (vsk)-notify.pkt.field_name + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk-consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk-qpair) notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) +
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang --- net/vmw_vsock/notify.c | 1041 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1171 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..03a0a1f --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,1041 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include + +#include +#include /* for NULL */ +#include + +#include "notify.h" +#include "af_vsock.h" + +#define PKT_FIELD(vsk, field_name) \ + (vsk)->notify.pkt.field_name + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) < + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk->consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space > ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window > bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk->qpair) > notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + if (!PKT_FIELD(vsk, peer_waiting_read)) +
[PATCH 3/6] VSOCK: notification implementation.
VSOCK control notifications for VMCI Stream Sockets protocol. Signed-off-by: George Zhang georgezh...@vmware.com --- net/vmw_vsock/notify.c | 1041 net/vmw_vsock/notify.h | 130 ++ 2 files changed, 1171 insertions(+), 0 deletions(-) create mode 100644 net/vmw_vsock/notify.c create mode 100644 net/vmw_vsock/notify.h diff --git a/net/vmw_vsock/notify.c b/net/vmw_vsock/notify.c new file mode 100644 index 000..03a0a1f --- /dev/null +++ b/net/vmw_vsock/notify.c @@ -0,0 +1,1041 @@ +/* + * VMware vSockets Driver + * + * Copyright (C) 2009-2012 VMware, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation version 2 and no later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * notify.c -- + * + * Linux control notifications for the VMCI Stream Sockets protocol. + */ + +#include linux/types.h + +#include linux/socket.h +#include linux/stddef.h /* for NULL */ +#include net/sock.h + +#include notify.h +#include af_vsock.h + +#define PKT_FIELD(vsk, field_name) \ + (vsk)-notify.pkt.field_name + +#define VSOCK_MAX_DGRAM_RESENDS 10 + +/* + * + * vsock_vmci_notify_waiting_write -- + * + * Determines if the conditions have been met to notify a waiting writer. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_write(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) + bool retval; + u64 notify_limit; + + if (!PKT_FIELD(vsk, peer_waiting_write)) + return false; + +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + /* +* When the sender blocks, we take that as a sign that the sender is +* faster than the receiver. To reduce the transmit rate of the sender, +* we delay the sending of the read notification by decreasing the +* write_notify_window. The notification is delayed until the number of +* bytes used in the queue drops below the write_notify_window. +*/ + + if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { + PKT_FIELD(vsk, peer_waiting_write_detected) = true; + if (PKT_FIELD(vsk, write_notify_window) PAGE_SIZE) { + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + } else { + PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; + if (PKT_FIELD(vsk, write_notify_window) + PKT_FIELD(vsk, write_notify_min_window)) + PKT_FIELD(vsk, write_notify_window) = + PKT_FIELD(vsk, write_notify_min_window); + + } + } + notify_limit = vsk-consume_size - PKT_FIELD(vsk, write_notify_window); +#else + notify_limit = 0; +#endif + + /* +* For now we ignore the wait information and just see if the free +* space exceeds the notify limit. Note that improving this function +* to be more intelligent will not require a protocol change and will +* retain compatibility between endpoints with mixed versions of this +* function. +* +* The notify_limit is used to delay notifications in the case where +* flow control is enabled. Below the test is expressed in terms of +* free space in the queue: if free_space ConsumeSize - +* write_notify_window then notify An alternate way of expressing this +* is to rewrite the expression to use the data ready in the receive +* queue: if write_notify_window bufferReady then notify as +* free_space == ConsumeSize - bufferReady. +*/ + retval = vmci_qpair_consume_free_space(vsk-qpair) notify_limit; +#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL + if (retval) { + /* +* Once we notify the peer, we reset the detected flag so the +* next wait will again cause a decrease in the window size. +*/ + + PKT_FIELD(vsk, peer_waiting_write_detected) = false; + } +#endif + return retval; +#else + return true; +#endif +} + +/* + * + * vsock_vmci_notify_waiting_read -- + * + * Determines if the conditions have been met to notify a waiting reader. + * + * Results: true if a notification should be sent, false otherwise. + * + * Side effects: None. + */ + +static bool vsock_vmci_notify_waiting_read(vsock_vmci_sock *vsk) +{ +#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) +