From 81c9653383c4ef07010c8efd1c5bd2d980804017 Mon Sep 17 00:00:00 2001 From: clyang Date: Wed, 2 Aug 2017 18:01:39 +0800 Subject: [PATCH] Improve ToS on IPv6 connections --- libtransmission/net.c | 64 ++++++++++++++++++++++++++++++++++----- libtransmission/net.h | 2 +- libtransmission/peer-io.c | 4 +-- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/libtransmission/net.c b/libtransmission/net.c index 588dc2b27..d96476808 100644 --- a/libtransmission/net.c +++ b/libtransmission/net.c @@ -153,22 +153,70 @@ int tr_address_compare(tr_address const* a, tr_address const* b) * TCP sockets **********************************************************************/ -void tr_netSetTOS(tr_socket_t s, int tos) +void tr_netSetTOS(tr_socket_t s, int tos, tr_address_type type) { + if (type == TR_AF_INET) + { #if defined(IP_TOS) && !defined(_WIN32) - if (setsockopt(s, IPPROTO_IP, IP_TOS, (void const*)&tos, sizeof(tos)) == -1) - { - char err_buf[512]; - tr_logAddNamedInfo("Net", "Can't set TOS '%d': %s", tos, tr_net_strerror(err_buf, sizeof(err_buf), sockerrno)); - } + if (setsockopt(s, IPPROTO_IP, IP_TOS, (void const*)&tos, sizeof(tos)) == -1) + { + char err_buf[512]; + tr_net_strerror(err_buf, sizeof(err_buf), sockerrno); + tr_logAddNamedInfo("Net", "Can't set TOS '%d': %s", tos, err_buf); + } #else - (void)s; - (void)tos; + (void)s; + (void)tos; #endif + } + else if (type == TR_AF_INET6) + { +#if defined(IPV6_TCLASS) && !defined(_WIN32) + + int dscp = 0; + + switch (tos) + { + case 0x10: + dscp = 0x20; /* lowcost (CS1) */ + break; + + case 0x08: + dscp = 0x28; /* throughput (AF11) */ + break; + + case 0x04: + dscp = 0x04; /* reliability */ + break; + + case 0x02: + dscp = 0x30; /* low delay (AF12) */ + break; + } + + if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, (void const*)&dscp, sizeof(dscp)) == -1) + { + char err_buf[512]; + tr_net_strerror(err_buf, sizeof(err_buf), sockerrno); + tr_logAddNamedInfo("Net", "Can't set IPv6 QoS '%d': %s", dscp, err_buf); + } + +#else + + (void)s; + (void)tos; + +#endif + } + else + { + /* program should never reach here! */ + tr_logAddNamedInfo("Net", "Something goes wrong while setting TOS/Traffic-Class"); + } } void tr_netSetCongestionControl(tr_socket_t s, char const* algorithm) diff --git a/libtransmission/net.h b/libtransmission/net.h index 8973dc57a..82577a04e 100644 --- a/libtransmission/net.h +++ b/libtransmission/net.h @@ -128,7 +128,7 @@ tr_socket_t tr_netBindTCP(tr_address const* addr, tr_port port, bool suppressMsg tr_socket_t tr_netAccept(tr_session* session, tr_socket_t bound, tr_address* setme_addr, tr_port* setme_port); -void tr_netSetTOS(tr_socket_t s, int tos); +void tr_netSetTOS(tr_socket_t s, int tos, tr_address_type type); void tr_netSetCongestionControl(tr_socket_t s, char const* algorithm); diff --git a/libtransmission/peer-io.c b/libtransmission/peer-io.c index 9fd955063..b84ed02de 100644 --- a/libtransmission/peer-io.c +++ b/libtransmission/peer-io.c @@ -637,7 +637,7 @@ static tr_peerIo* tr_peerIoNew(tr_session* session, tr_bandwidth* parent, tr_add if (socket.type == TR_PEER_SOCKET_TYPE_TCP) { - tr_netSetTOS(socket.handle.tcp, session->peerSocketTOS); + tr_netSetTOS(socket.handle.tcp, session->peerSocketTOS, addr->type); maybeSetCongestionAlgorithm(socket.handle.tcp, session->peer_congestion_algorithm); } @@ -993,7 +993,7 @@ int tr_peerIoReconnect(tr_peerIo* io) io->event_write = event_new(session->event_base, io->socket.handle.tcp, EV_WRITE, event_write_cb, io); event_enable(io, pendingEvents); - tr_netSetTOS(io->socket.handle.tcp, session->peerSocketTOS); + tr_netSetTOS(io->socket.handle.tcp, session->peerSocketTOS, io->addr.type); maybeSetCongestionAlgorithm(io->socket.handle.tcp, session->peer_congestion_algorithm); return 0;