Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set DSCP bits for IPv6 when setting traffic class. #4650

Closed
wants to merge 5 commits into from
Closed

Set DSCP bits for IPv6 when setting traffic class. #4650

wants to merge 5 commits into from

Conversation

earthling
Copy link
Contributor

Linux uses different socket options to set the traffic class (DSCP) on IPv6. I've tested this fix with UDP, but not TCP (but as this is an IP option, it should be fine). There isn't an easy way to verify this change outside of tcpdump. In this exchange, a native udp client sends a datagram with a high priority DSCP (14) to a Netty based echo server where we have bootstrap.setTrafficClass(10).

> sudo tcpdump -i lo -e -vvv port 8888
10:02:29.648014 00:00:00:00:00:00 (oui Ethernet) > 00:00:00:00:00:00 (oui Ethernet), ethertype IPv6 (0x86dd), length 71: (class 0x0e, hlim 64, next-header UDP (17) payload length: 17) ip6-localhost.33865 > ip6-localhost.8888: [udp sum ok] UDP, length 9
10:02:29.662014 00:00:00:00:00:00 (oui Ethernet) > 00:00:00:00:00:00 (oui Ethernet), ethertype IPv6 (0x86dd), length 71: (class 0x0a, hlim 64, next-header UDP (17) payload length: 17) ip6-localhost.8888 > ip6-localhost.33865: [udp sum ok] UDP, length 9

Scroll down the line to see the expected class 0x0a - without this change, you don't get that.

@normanmaurer
Copy link
Member

@earthling shouldn't we either use the "old way" or the "new way" depending if ipv6 is used or not ? Also could you please sign our ICLA and squash the commits ?
http://netty.io/s/icla

@normanmaurer normanmaurer self-assigned this Jan 4, 2016
@normanmaurer normanmaurer added this to the 4.0.34.Final milestone Jan 4, 2016
@earthling
Copy link
Contributor Author

I'm not sure what you mean by 'old way' and 'new way'? It seemed to me like the same socket could be used for IPv4 and IPv6, so I just set both socket options.

I signed the ICLA and I'll try to squash the commits (I'm terrible with git). Should I open a new pull request for the squashed commit?

@normanmaurer
Copy link
Member

@earthling well I think we either need to use one or the other option set depending on ipv6 or ipv4. And we also need to fix this for the "get" operation as well.

@earthling
Copy link
Contributor Author

@normanmaurer are you suggesting to check if the socket type is AF_INET or if IPV6_V6ONLY is true? What about the case when the socket type is AF_INET6 and IPV6_V6ONLY is false? would you not want to cover both ipv4 and ipv6 at the same time? Or are you suggesting we expose these separately in the Java API? Setting the IPv6 option on an IPv4 socket (or setting the IPv4 option on an IPv6 socket) seems harmless. I agree we need to fix the 'get' operation, I can fix that once we settle on an implementation for the 'set' operation.

@normanmaurer
Copy link
Member

@earthling yeah I would check the socket type. I think this should be good enough. Depending on the socket type we then use the correct opts for set and get.

@earthling
Copy link
Contributor Author

Something like this then?

    if (socketType == AF_INET) {
        netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval));
    }
    else {
        netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval));
        netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval));
    }

@normanmaurer
Copy link
Member

@earthling yeah but for the "else" you should only need:

        netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval));

@earthling
Copy link
Contributor Author

Yes, but then it wouldn't work on IPv4 packets sent via that socket.

@earthling
Copy link
Contributor Author

A full accounting would look like:

    if (socketType == AF_INET) {
        netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval));
    }
    else if (IPV6_V6ONLY) {
        netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval));
    }
    else {
        netty_unix_socket_setOption(env, fd, IPPROTO_IP, IP_TOS, &optval, sizeof(optval));
        netty_unix_socket_setOption(env, fd, IPPROTO_IPV6, IPV6_TCLASS, &optval, sizeof(optval));
    }

@normanmaurer
Copy link
Member

@earthling makes sense... But what we do with the get ? I guess just "query" on in the else should be good enough. Agree ?

Also please use the coding style we use in our .c files and update the commit message to match our template:

http://netty.io/wiki/writing-a-commit-message.html

@earthling
Copy link
Contributor Author

Okay, will do. Should I make a new pull request with all the changes?

@normanmaurer
Copy link
Member

@earthling you can also just update this one...

Motivation:

Attempting to set the ipv6 traffic class on an ipv4 only socket should not cause an exception.

Modifications:

Suppress the exception when setsockopt error is ENOPROTOOPT.

Result:

IPv4 only sockets will work as before.
@earthling
Copy link
Contributor Author

@normanmaurer Thinking about the 'get' operation... I think it's going to be okay to just use the IP_TOS value. getsockopt returns this value correctly for AF_INET6 sockets (even ones when IPV6_V6ONLY is true). I did change the 'set' operation to not raise an exception if we try to set IPV6_TCLASS on an AF_INET only socket.

@normanmaurer
Copy link
Member

@earthling sounds good. Let me know once you are done.

@earthling
Copy link
Contributor Author

@normanmaurer I think I'm done. Thanks for working this out with me.

@normanmaurer
Copy link
Member

@earthling so the get operation not need any changes ?

@earthling
Copy link
Contributor Author

I don't believe so, no. For all socket types, the value set for IP_TOS is returned with getsockopt, and we set IP_TOS for all socket types.

@normanmaurer
Copy link
Member

@earthling thanks!

Squashed your commits, adjusted the commit message and cherry-picked into 4.0 (ae470e3) and 4.1(c205e2b)

@earthling
Copy link
Contributor Author

@normanmaurer Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants