From 6cb8f011c9ff83fddb6bffbabbe280cfeb64778f Mon Sep 17 00:00:00 2001 From: Riza Sulistyo Date: Wed, 5 Oct 2016 09:07:17 +0000 Subject: Re #1963: Implement QoS for IPv6 for platform that supports IPV6_TCLASS. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5444 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/include/pj/sock.h | 13 ++++++++++++ pjlib/src/pj/sock_bsd.c | 8 +++++++ pjlib/src/pj/sock_common.c | 5 +++++ pjlib/src/pj/sock_qos_bsd.c | 52 ++++++++++++++++++++++++++++++++++++++------- 4 files changed, 70 insertions(+), 8 deletions(-) diff --git a/pjlib/include/pj/sock.h b/pjlib/include/pj/sock.h index 44d0fecd..e0b64d8a 100644 --- a/pjlib/include/pj/sock.h +++ b/pjlib/include/pj/sock.h @@ -276,6 +276,19 @@ extern const pj_uint16_t PJ_IPTOS_MINCOST; #endif +/** IPV6_TCLASS optname in setsockopt(). @see pj_IPV6_TCLASS() */ +extern const pj_uint16_t PJ_IPV6_TCLASS; + + +#if defined(PJ_DLL) + /** Get #PJ_IPV6_TCLASS constant */ + PJ_DECL(int) pj_IPV6_TCLASS(void); +#else + /** Get #PJ_IPV6_TCLASS constant */ +# define pj_IPV6_TCLASS() PJ_IPV6_TCLASS +#endif + + /** * Values to be specified as \c optname when calling #pj_sock_setsockopt() * or #pj_sock_getsockopt(). diff --git a/pjlib/src/pj/sock_bsd.c b/pjlib/src/pj/sock_bsd.c index dc015d84..d6b18990 100644 --- a/pjlib/src/pj/sock_bsd.c +++ b/pjlib/src/pj/sock_bsd.c @@ -131,6 +131,14 @@ const pj_uint16_t PJ_IPTOS_MINCOST = 0x02; #endif +/* IPV6_TCLASS */ +#ifdef IPV6_TCLASS +const pj_uint16_t PJ_IPV6_TCLASS = IPV6_TCLASS; +#else +const pj_uint16_t PJ_IPV6_TCLASS = 0xFFFF; +#endif + + /* optname values. */ const pj_uint16_t PJ_SO_TYPE = SO_TYPE; const pj_uint16_t PJ_SO_RCVBUF = SO_RCVBUF; diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c index 1a4f8a11..0ea25fbc 100644 --- a/pjlib/src/pj/sock_common.c +++ b/pjlib/src/pj/sock_common.c @@ -1244,6 +1244,11 @@ PJ_DEF(int) pj_IPTOS_MINCOST(void) return PJ_IPTOS_MINCOST; } +PJ_DEF(int) pj_IPV6_TCLASS(void) +{ + return PJ_IPV6_TCLASS; +} + PJ_DEF(pj_uint16_t) pj_SO_TYPE(void) { return PJ_SO_TYPE; diff --git a/pjlib/src/pj/sock_qos_bsd.c b/pjlib/src/pj/sock_qos_bsd.c index c4c54ba5..55a7e1e0 100644 --- a/pjlib/src/pj/sock_qos_bsd.c +++ b/pjlib/src/pj/sock_qos_bsd.c @@ -22,7 +22,7 @@ #include /* This is the implementation of QoS with BSD socket's setsockopt(), - * using IP_TOS and SO_PRIORITY + * using IP_TOS/IPV6_TCLASS and SO_PRIORITY */ #if !defined(PJ_QOS_IMPLEMENTATION) || PJ_QOS_IMPLEMENTATION==PJ_QOS_BSD @@ -41,10 +41,30 @@ PJ_DEF(pj_status_t) pj_sock_set_qos_params(pj_sock_t sock, /* Set TOS/DSCP */ if (param->flags & PJ_QOS_PARAM_HAS_DSCP) { + /* We need to know if the socket is IPv4 or IPv6 */ + pj_sockaddr sa; + int salen = sizeof(salen); + /* Value is dscp_val << 2 */ int val = (param->dscp_val << 2); - status = pj_sock_setsockopt(sock, pj_SOL_IP(), pj_IP_TOS(), - &val, sizeof(val)); + + status = pj_sock_getsockname(sock, &sa, &salen); + if (status != PJ_SUCCESS) + return status; + + if (sa.addr.sa_family == pj_AF_INET()) { + /* In IPv4, the DS field goes in the TOS field */ + status = pj_sock_setsockopt(sock, pj_SOL_IP(), pj_IP_TOS(), + &val, sizeof(val)); + } else if (sa.addr.sa_family == pj_AF_INET6()) { + /* In IPv6, the DS field goes in the Traffic Class field */ + status = pj_sock_setsockopt(sock, pj_SOL_IPV6(), + pj_IPV6_TCLASS(), + &val, sizeof(val)); + } else { + status = PJ_EINVAL; + } + if (status != PJ_SUCCESS) { param->flags &= ~(PJ_QOS_PARAM_HAS_DSCP); last_err = status; @@ -84,17 +104,33 @@ PJ_DEF(pj_status_t) pj_sock_get_qos_params(pj_sock_t sock, { pj_status_t last_err = PJ_ENOTSUP; int val, optlen; + pj_sockaddr sa; + int salen = sizeof(salen); pj_status_t status; pj_bzero(p_param, sizeof(*p_param)); /* Get DSCP/TOS value */ - optlen = sizeof(val); - status = pj_sock_getsockopt(sock, pj_SOL_IP(), pj_IP_TOS(), - &val, &optlen); + status = pj_sock_getsockname(sock, &sa, &salen); if (status == PJ_SUCCESS) { - p_param->flags |= PJ_QOS_PARAM_HAS_DSCP; - p_param->dscp_val = (pj_uint8_t)(val >> 2); + optlen = sizeof(val); + if (sa.addr.sa_family == pj_AF_INET()) { + status = pj_sock_getsockopt(sock, pj_SOL_IP(), pj_IP_TOS(), + &val, &optlen); + } else if (sa.addr.sa_family == pj_AF_INET6()) { + status = pj_sock_getsockopt(sock, pj_SOL_IPV6(), + pj_IPV6_TCLASS(), + &val, &optlen); + } else { + status = PJ_EINVAL; + } + + if (status == PJ_SUCCESS) { + p_param->flags |= PJ_QOS_PARAM_HAS_DSCP; + p_param->dscp_val = (pj_uint8_t)(val >> 2); + } else { + last_err = status; + } } else { last_err = status; } -- cgit v1.2.3