summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiza Sulistyo <riza@teluu.com>2016-10-05 09:07:17 +0000
committerRiza Sulistyo <riza@teluu.com>2016-10-05 09:07:17 +0000
commit6cb8f011c9ff83fddb6bffbabbe280cfeb64778f (patch)
tree7763e2a78d151d728fe5a5662a494d19de559958
parentc8023fd26f3b19fd0cebf891b0fc2b3082abb21e (diff)
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
-rw-r--r--pjlib/include/pj/sock.h13
-rw-r--r--pjlib/src/pj/sock_bsd.c8
-rw-r--r--pjlib/src/pj/sock_common.c5
-rw-r--r--pjlib/src/pj/sock_qos_bsd.c52
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 <pj/string.h>
/* 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;
}