1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

ip tos support

This commit is contained in:
Andy Green 2021-02-04 09:08:17 +00:00
parent 8d48d8f3fb
commit eb782bd41e
14 changed files with 285 additions and 0 deletions

View file

@ -78,6 +78,18 @@ enum lws_client_connect_ssl_connection_flags {
/**< client is a link between SS client and SS proxy */
LCCSCF_SECSTREAM_PROXY_ONWARD = (1 << 23),
/**< client the SS proxy's onward connection */
LCCSCF_IP_LOW_LATENCY = (1 << 24),
/**< set the "low delay" bit on the IP packets of this connection */
LCCSCF_IP_HIGH_THROUGHPUT = (1 << 25),
/**< set the "high throughput" bit on the IP packets of this
* connection */
LCCSCF_IP_HIGH_RELIABILITY = (1 << 26),
/**< set the "high reliability" bit on the IP packets of this
* connection */
LCCSCF_IP_LOW_COST = (1 << 27),
/**< set the "minimize monetary cost" bit on the IP packets of this
* connection */
};
/** struct lws_client_connect_info - parameters to connect with when using
@ -177,6 +189,13 @@ struct lws_client_connect_info {
* to the client connection.
*/
uint8_t priority;
/**< 0 means normal priority... otherwise sets the IP priority on
* packets coming from this connection, from 1 - 7. Setting 7
* (network management priority) requires CAP_NET_ADMIN capability but
* the others can be set by anyone.
*/
#if defined(LWS_ROLE_MQTT)
const lws_mqtt_client_connect_param_t *mqtt_cp;
#else

View file

@ -128,6 +128,15 @@ enum {
/**< follow redirects */
LWSSSPOLF_HTTP_MULTIPART_IN = (1 << 17),
/**< handle inbound multipart mime at SS level */
LWSSSPOLF_ATTR_LOW_LATENCY = (1 << 18),
/**< stream requires low latency */
LWSSSPOLF_ATTR_HIGH_THROUGHPUT = (1 << 19),
/**< stream requires high throughput */
LWSSSPOLF_ATTR_HIGH_RELIABILITY = (1 << 20),
/**< stream requires high reliability */
LWSSSPOLF_ATTR_LOW_COST = (1 << 21),
/**< stream is not critical and should be handled as cheap as poss */
};
typedef struct lws_ss_trust_store {
@ -334,6 +343,8 @@ typedef struct lws_ss_policy {
uint8_t protocol; /**< protocol index */
uint8_t client_cert; /**< which client cert to apply
0 = none, 1+ = cc 0+ */
uint8_t priority; /* 0 = normal, 6 = max normal,
* 7 = network management */
} lws_ss_policy_t;
#if !defined(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY)

View file

@ -281,6 +281,20 @@ lws_adopt_ss_server_accept(struct lws *new_wsi)
h->policy = new_wsi->a.vhost->ss_handle->policy;
/* apply requested socket options */
if (lws_plat_set_socket_options_ip(new_wsi->desc.sockfd,
h->policy->priority,
(LCCSCF_IP_LOW_LATENCY *
!!(h->policy->flags & LWSSSPOLF_ATTR_LOW_LATENCY)) |
(LCCSCF_IP_HIGH_THROUGHPUT *
!!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_THROUGHPUT)) |
(LCCSCF_IP_HIGH_RELIABILITY *
!!(h->policy->flags & LWSSSPOLF_ATTR_HIGH_RELIABILITY)) |
(LCCSCF_IP_LOW_COST *
!!(h->policy->flags & LWSSSPOLF_ATTR_LOW_COST))))
lwsl_warn("%s: %s: unable to set ip options\n",
__func__, new_wsi->lc.gutag);
/*
* add us to the list of clients that came in from the server
*/

View file

@ -154,6 +154,9 @@ lws_client_connect_via_info(const struct lws_client_connect_info *i)
wsi->seq = i->seq;
wsi->flags = i->ssl_connection;
wsi->c_pri = i->priority;
if (i->retry_and_idle_policy)
wsi->retry_policy = i->retry_and_idle_policy;
else

View file

@ -324,6 +324,12 @@ ads_known:
goto try_next_dns_result_closesock;
}
/* apply requested socket options */
if (lws_plat_set_socket_options_ip(wsi->desc.sockfd,
wsi->c_pri, wsi->flags))
lwsl_warn("%s: %s: unable to set ip options\n",
__func__, wsi->lc.gutag);
lwsl_debug("%s: %s: WAITING_CONNECT\n", __func__, wsi->lc.gutag);
lwsi_set_state(wsi, LRS_WAITING_CONNECT);

View file

@ -898,6 +898,7 @@ struct lws {
char chunk_parser; /* enum lws_chunk_parser */
uint8_t addrinfo_idx;
uint8_t sys_tls_client_cert;
uint8_t c_pri;
#endif
#if defined(LWS_WITH_CGI) || defined(LWS_WITH_CLIENT)
char reason_bf; /* internal writeable callback reason bitfield */
@ -1067,6 +1068,9 @@ int
lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
int unix_skt);
int
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags);
int
lws_plat_check_connection_error(struct lws *wsi);

View file

@ -139,6 +139,63 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
return lws_plat_set_nonblocking(fd);
}
static const int ip_opt_lws_flags[] = {
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
LCCSCF_IP_HIGH_RELIABILITY, LCCSCF_IP_LOW_COST
}, ip_opt_val[] = {
IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, IPTOS_MINCOST
};
#if !defined(LWS_WITH_NO_LOGS)
static const char *ip_opt_names[] = {
"LOWDELAY", "THROUGHPUT", "RELIABILITY", "MINCOST"
};
#endif
int
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
{
int optval = (int)pri, ret = 0, n;
socklen_t optlen = sizeof(optval);
#if !defined(LWS_WITH_NO_LOGS)
int en;
#endif
#if defined(SO_PRIORITY)
if (pri) { /* 0 is the default already */
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY,
(const void *)&optval, optlen) < 0) {
#if !defined(LWS_WITH_NO_LOGS)
en = errno;
lwsl_warn("%s: unable to set socket pri %d: errno %d\n",
__func__, (int)pri, en);
#endif
ret = 1;
} else
lwsl_notice("%s: set pri %u\n", __func__, pri);
}
#endif
for (n = 0; n < 4; n++) {
if (!(lws_flags & ip_opt_lws_flags[n]))
continue;
optval = (int)ip_opt_val[n];
if (setsockopt(fd, IPPROTO_IP, IP_TOS, (const void *)&optval,
optlen) < 0) {
#if !defined(LWS_WITH_NO_LOGS)
en = errno;
lwsl_warn("%s: unable to set %s: errno %d\n", __func__,
ip_opt_names[n], en);
#endif
ret = 1;
} else
lwsl_notice("%s: set ip flag %s\n", __func__,
ip_opt_names[n]);
}
return ret;
}
/* cast a struct sockaddr_in6 * into addr for ipv6 */
int

View file

@ -256,6 +256,12 @@ lws_plat_inet_pton(int af, const char *src, void *dst)
return 1;
}
int
lws_plat_set_socket_options_ip(int fd, uint8_t pri, unsigned int lws_flags)
{
return 0;
}
#if defined(LWS_WITH_MBEDTLS)
int
lws_plat_mbedtls_net_send(void *ctx, const uint8_t *buf, size_t len)

View file

@ -46,6 +46,8 @@
#endif
#endif
#include <netinet/ip.h>
int
lws_send_pipe_choked(struct lws *wsi)
{
@ -188,6 +190,69 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
return lws_plat_set_nonblocking(fd);
}
static const int ip_opt_lws_flags[] = {
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
LCCSCF_IP_HIGH_RELIABILITY, LCCSCF_IP_LOW_COST
}, ip_opt_val[] = {
IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY, IPTOS_MINCOST
};
#if !defined(LWS_WITH_NO_LOGS)
static const char *ip_opt_names[] = {
"LOWDELAY", "THROUGHPUT", "RELIABILITY", "MINCOST"
};
#endif
int
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
{
int optval = (int)pri, ret = 0, n;
socklen_t optlen = sizeof(optval);
#if !defined(LWS_WITH_NO_LOGS)
int en;
#endif
#if !defined(__APPLE__) && \
!defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && \
!defined(__NetBSD__) && \
!defined(__OpenBSD__) && \
!defined(__HAIKU__)
/* the BSDs don't have SO_PRIORITY */
if (pri) { /* 0 is the default already */
if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY,
(const void *)&optval, optlen) < 0) {
#if !defined(LWS_WITH_NO_LOGS)
en = errno;
lwsl_warn("%s: unable to set socket pri %d: errno %d\n",
__func__, (int)pri, en);
#endif
ret = 1;
} else
lwsl_notice("%s: set pri %u\n", __func__, pri);
}
#endif
for (n = 0; n < 4; n++) {
if (!(lws_flags & ip_opt_lws_flags[n]))
continue;
optval = (int)ip_opt_val[n];
if (setsockopt(fd, IPPROTO_IP, IP_TOS, (const void *)&optval,
optlen) < 0) {
#if !defined(LWS_WITH_NO_LOGS)
en = errno;
lwsl_warn("%s: unable to set %s: errno %d\n", __func__,
ip_opt_names[n], en);
#endif
ret = 1;
} else
lwsl_notice("%s: set ip flag %s\n", __func__,
ip_opt_names[n]);
}
return ret;
}
/* cast a struct sockaddr_in6 * into addr for ipv6 */

View file

@ -144,6 +144,19 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
return lws_plat_set_nonblocking(fd);
}
int
lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
{
/*
* Seems to require "differeniated services" but no docs
*
* https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
* https://docs.microsoft.com/en-us/previous-versions/windows/desktop/qos/differentiated-services
*/
lwsl_warn("%s: not implemented on windows platform\n", __func__);
return 0;
}
int
lws_interface_to_sa(int ipv6,

View file

@ -394,6 +394,39 @@ payload buffering (in bytes) the client will hold for this type of stream. If
the client sends a lot of data without any flow control, this may need to
be correspondingly large. Default is 32KB.
### `attr_priority`
A number between 0 (normal priority) and 6 (very high priority). 7 is also
possible, but requires CAP_NET_ADMIN on Linux and is reserved for network
administration packets. Normally default priority is fine, but under some
conditions when transporting over IP packets, you may want to control the
IP packet ToS priority for the streamtype by using this.
### `attr_low_latency`
This is a flag indicating that the streamtype packets should be transported
in a way that results in lower latency where there is a choice. For IP packets,
this sets the ToS "low delay" flag on packets from this streamtype.
### `attr_high_throughput`
This is a flag indicating that this streamtype should be expected to produce
bulk content that requires high throughput. For IP packets,
this sets the ToS "high throughput" flag on packets from this streamtype.
### `attr_high_reliability`
This is a flag indicating that extra efforts should be made to deliver packets
from this streamtype where possible. For IP packets, this sets the ToS "high
reliability" flag on packets from this streamtype.
### `attr_low_cost`
This is a flag indicating that packets from this streamtype should be routed as
inexpensively as possible by trading off latency and reliability where there is
a choice. For IP packets, this sets the ToS "low cost" flag on packets from
this streamtype.
### `metadata`
This allows declaring basically dynamic symbol names to be used by the streamtype,

View file

@ -53,6 +53,11 @@ static const char * const lejp_tokens_policy[] = {
"s[].*.allow_redirects",
"s[].*.urgent_tx",
"s[].*.urgent_rx",
"s[].*.attr_priority",
"s[].*.attr_low_latency",
"s[].*.attr_high_throughput",
"s[].*.attr_high_reliability",
"s[].*.attr_low_cost",
"s[].*.long_poll",
"s[].*.retry",
"s[].*.timeout_ms",
@ -142,6 +147,11 @@ typedef enum {
LSSPPT_ALLOW_REDIRECTS,
LSSPPT_URGENT_TX,
LSSPPT_URGENT_RX,
LSSPPT_ATTR_PRIORITY,
LSSPPT_ATTR_LOW_LATENCY,
LSSPPT_ATTR_HIGH_THROUGHPUT,
LSSPPT_ATTR_HIGH_RELIABILITY,
LSSPPT_ATTR_LOW_COST,
LSSPPT_LONG_POLL,
LSSPPT_RETRYPTR,
LSSPPT_DEFAULT_TIMEOUT_MS,
@ -667,6 +677,10 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
a->curr[LTY_POLICY].p->timeout_ms = (uint32_t)atoi(ctx->buf);
break;
case LSSPPT_ATTR_PRIORITY:
a->curr[LTY_POLICY].p->priority = (uint8_t)atoi(ctx->buf);
break;
case LSSPPT_OPPORTUNISTIC:
if (reason == LEJPCB_VAL_TRUE)
a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_OPPORTUNISTIC;
@ -708,6 +722,29 @@ lws_ss_policy_parser_cb(struct lejp_ctx *ctx, char reason)
LWSSSPOLF_HTTP_MULTIPART_IN;
return 0;
case LSSPPT_ATTR_LOW_LATENCY:
if (reason == LEJPCB_VAL_TRUE)
a->curr[LTY_POLICY].p->flags |=
LWSSSPOLF_ATTR_LOW_LATENCY;
return 0;
case LSSPPT_ATTR_HIGH_THROUGHPUT:
if (reason == LEJPCB_VAL_TRUE)
a->curr[LTY_POLICY].p->flags |=
LWSSSPOLF_ATTR_HIGH_THROUGHPUT;
return 0;
case LSSPPT_ATTR_HIGH_RELIABILITY:
if (reason == LEJPCB_VAL_TRUE)
a->curr[LTY_POLICY].p->flags |=
LWSSSPOLF_ATTR_HIGH_RELIABILITY;
return 0;
case LSSPPT_ATTR_LOW_COST:
if (reason == LEJPCB_VAL_TRUE)
a->curr[LTY_POLICY].p->flags |= LWSSSPOLF_ATTR_LOW_COST;
return 0;
case LSSPPT_RETRYPTR:
bot = a->heads[LTY_BACKOFF].b;
while (bot) {

View file

@ -592,6 +592,21 @@ _lws_ss_client_connect(lws_ss_handle_t *h, int is_retry, void *conn_if_sspc_onw)
if (h->policy->flags & LWSSSPOLF_WAKE_SUSPEND__VALIDITY)
i.ssl_connection |= LCCSCF_WAKE_SUSPEND__VALIDITY;
/* translate policy attributes to IP ToS flags */
if (h->policy->flags & LCCSCF_IP_LOW_LATENCY)
i.ssl_connection |= LWSSSPOLF_ATTR_LOW_LATENCY;
if (h->policy->flags & LCCSCF_IP_HIGH_THROUGHPUT)
i.ssl_connection |= LWSSSPOLF_ATTR_HIGH_THROUGHPUT;
if (h->policy->flags & LCCSCF_IP_HIGH_RELIABILITY)
i.ssl_connection |= LWSSSPOLF_ATTR_HIGH_RELIABILITY;
if (h->policy->flags & LCCSCF_IP_LOW_COST)
i.ssl_connection |= LWSSSPOLF_ATTR_LOW_COST;
/* mark the connection with the streamtype priority from the policy */
i.priority = h->policy->priority;
i.ssl_connection |= LCCSCF_SECSTREAM_CLIENT;
if (conn_if_sspc_onw) {

View file

@ -620,6 +620,8 @@ int main(int argc, const char **argv)
printf("\t.timeout_ms = %u,\n", pol->timeout_ms);
if (pol->flags)
printf("\t.flags = 0x%x,\n", pol->flags);
if (pol->flags)
printf("\t.priority = 0x%x,\n", (unsigned int)pol->priority);
if (pol->port)
printf("\t.port = %u,\n", pol->port);
if (pol->metadata_count)