diff options
author | Micael Karlberg <[email protected]> | 2018-07-18 12:05:00 +0200 |
---|---|---|
committer | Micael Karlberg <[email protected]> | 2018-09-18 14:50:18 +0200 |
commit | 1a3aca0a849af0bae994c9cf89de0dcfe7b310c2 (patch) | |
tree | b8085134c12d89b06afd3a251005e074e186ca4c | |
parent | ebd626e7b4259bdfb4ddb34ce2d298d0feb0a1c8 (diff) | |
download | otp-1a3aca0a849af0bae994c9cf89de0dcfe7b310c2.tar.gz otp-1a3aca0a849af0bae994c9cf89de0dcfe7b310c2.tar.bz2 otp-1a3aca0a849af0bae994c9cf89de0dcfe7b310c2.zip |
[socket-nif] Add support for socket (level ipv6) option mtu_discover
Added support for the VPv6 socket option MTU_DISCOVER.
OTP-14831.
-rw-r--r-- | erts/doc/src/socket_usage.xml | 21 | ||||
-rw-r--r-- | erts/emulator/nifs/common/socket_nif.c | 190 | ||||
-rw-r--r-- | erts/preloaded/ebin/socket.beam | bin | 51480 -> 51660 bytes | |||
-rw-r--r-- | erts/preloaded/src/socket.erl | 16 |
4 files changed, 217 insertions, 10 deletions
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml index cdd98090e8..247cd0eccb 100644 --- a/erts/doc/src/socket_usage.xml +++ b/erts/doc/src/socket_usage.xml @@ -145,7 +145,7 @@ <cell>none</cell> </row> <row> - <cell>peep_off</cell> + <cell>peek_off</cell> <cell>integer()</cell> <cell>yes</cell> <cell>yes</cell> @@ -255,7 +255,7 @@ </row> <row> <cell>mtu_discover</cell> - <cell>ip_mtu_discover()</cell> + <cell>ip_pmtudisc()</cell> <cell>yes</cell> <cell>yes</cell> <cell>none</cell> @@ -377,6 +377,13 @@ <cell>Get: Only after the socket has been connected</cell> </row> <row> + <cell>mtu_discover</cell> + <cell>ipv6_pmtudisc()</cell> + <cell>yes</cell> + <cell>yes</cell> + <cell>none</cell> + </row> + <row> <cell>v6only</cell> <cell>boolean()</cell> <cell>yes</cell> @@ -406,14 +413,14 @@ <cell>integer()</cell> <cell>yes</cell> <cell>yes</cell> - <cell>type = stream, protocol = tcp</cell> + <cell>none</cell> </row> <row> <cell>nodelay</cell> <cell>boolean()</cell> <cell>yes</cell> <cell>yes</cell> - <cell>type = stream, protocol = tcp</cell> + <cell>none</cell> </row> </table> @@ -431,7 +438,7 @@ <cell>boolean()</cell> <cell>yes</cell> <cell>yes</cell> - <cell>type = dgram, protocol = udp</cell> + <cell>none</cell> </row> </table> @@ -449,14 +456,14 @@ <cell>integer()</cell> <cell>yes</cell> <cell>yes</cell> - <cell>protocol = sctp</cell> + <cell>none</cell> </row> <row> <cell>nodelay</cell> <cell>boolean()</cell> <cell>yes</cell> <cell>yes</cell> - <cell>protocol = sctp</cell> + <cell>none</cell> </row> </table> diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 0222d58e6d..d2f7e21ad0 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -389,6 +389,7 @@ typedef union { #define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6 #define SOCKET_OPT_IPV6_HOPLIMIT 12 #define SOCKET_OPT_IPV6_MTU 17 +#define SOCKET_OPT_IPV6_MTU_DISCOVER 18 #define SOCKET_OPT_IPV6_V6ONLY 33 #define SOCKET_OPT_TCP_CONGESTION 1 @@ -1014,6 +1015,11 @@ static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env, SocketDescriptor* descP, ERL_NIF_TERM eVal); #endif +#if defined(IPV6_MTU_DISCOVER) +static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IPV6_V6ONLY) static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, SocketDescriptor* descP, @@ -1237,6 +1243,10 @@ static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env, SocketDescriptor* descP); #endif +#if defined(IPV6_MTU_DISCOVER) +static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + SocketDescriptor* descP); +#endif #if defined(IPV6_V6ONLY) static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, SocketDescriptor* descP); @@ -1451,6 +1461,16 @@ static void encode_ip_pmtudisc(ErlNifEnv* env, int val, ERL_NIF_TERM* eVal); #endif +#if defined(IPV6_MTU_DISCOVER) +static char* decode_ipv6_pmtudisc(ErlNifEnv* env, + ERL_NIF_TERM eVal, + int* val); +#endif +#if defined(IPV6_MTU_DISCOVER) +static void encode_ipv6_pmtudisc(ErlNifEnv* env, + int val, + ERL_NIF_TERM* eVal); +#endif /* static BOOLEAN_T decode_bool(ErlNifEnv* env, @@ -4977,6 +4997,12 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, break; #endif +#if defined(IPV6_MTU_DISCOVER) + case SOCKET_OPT_IPV6_MTU_DISCOVER: + result = nsetopt_lvl_ipv6_mtu_discover(env, descP, eVal); + break; +#endif + #if defined(IPV6_V6ONLY) case SOCKET_OPT_IPV6_V6ONLY: result = nsetopt_lvl_ipv6_v6only(env, descP, eVal); @@ -5038,6 +5064,42 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env, #endif +/* nsetopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option + * + * The value is an atom of the type ipv6_pmtudisc(). + */ +#if defined(IPV6_MTU_DISCOVER) +static +ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + SocketDescriptor* descP, + ERL_NIF_TERM eVal) +{ + ERL_NIF_TERM result; + int val; + char* xres; + int res; + + if ((xres = decode_ipv6_pmtudisc(env, eVal, &val)) != NULL) { + + result = esock_make_error_str(env, xres); + + } else { + + res = socket_setopt(descP->sock, SOL_IPV6, IPV6_MTU_DISCOVER, + &val, sizeof(val)); + + if (res != 0) + result = esock_make_error_errno(env, sock_errno()); + else + result = esock_atom_ok; + + } + + return result; +} +#endif + + #if defined(IPV6_V6ONLY) static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, @@ -6731,6 +6793,12 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, break; #endif +#if defined(IPV6_MTU_DISCOVER) + case SOCKET_OPT_IPV6_MTU_DISCOVER: + result = ngetopt_lvl_ipv6_mtu_discover(env, descP); + break; +#endif + #if defined(IPV6_V6ONLY) case SOCKET_OPT_IPV6_V6ONLY: result = ngetopt_lvl_ipv6_v6only(env, descP); @@ -6771,6 +6839,35 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env, #endif +/* ngetopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option + */ +#if defined(IPV6_MTU_DISCOVER) +static +ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + SocketDescriptor* descP) +{ + ERL_NIF_TERM result; + ERL_NIF_TERM eMtuDisc; + int mtuDisc; + SOCKOPTLEN_T mtuDiscSz = sizeof(mtuDisc); + int res; + + res = sock_getopt(descP->sock, SOL_IPV6, IPV6_MTU_DISCOVER, + &mtuDisc, &mtuDiscSz); + + if (res != 0) { + result = esock_make_error_errno(env, sock_errno()); + } else { + encode_ipv6_pmtudisc(env, mtuDisc, &eMtuDisc); + result = esock_make_ok2(env, eMtuDisc); + } + + return result; + +} +#endif + + #if defined(IPV6_V6ONLY) static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, @@ -7723,6 +7820,57 @@ char* decode_ip_pmtudisc(ErlNifEnv* env, ERL_NIF_TERM eVal, int* val) +/* +++ decode the ipv6 socket option MTU_DISCOVER +++ + * The (ip) option can be provide in two ways: + * + * atom() | integer() + * + * When its an atom it can have the values: + * + * want | dont | do | probe + * + */ +#if defined(IPV6_MTU_DISCOVER) +static +char* decode_ipv6_pmtudisc(ErlNifEnv* env, ERL_NIF_TERM eVal, int* val) +{ + char* res = NULL; + + if (IS_ATOM(env, eVal)) { + + if (COMPARE(eVal, atom_want) == 0) { + *val = IPV6_PMTUDISC_WANT; + } else if (COMPARE(eVal, atom_dont) == 0) { + *val = IPV6_PMTUDISC_DONT; + } else if (COMPARE(eVal, atom_do) == 0) { + *val = IPV6_PMTUDISC_DO; + } else if (COMPARE(eVal, atom_probe) == 0) { + *val = IPV6_PMTUDISC_PROBE; + } else { + *val = -1; + res = ESOCK_STR_EINVAL; + } + + } else if (IS_NUM(env, eVal)) { + + if (!GET_INT(env, eVal, val)) { + *val = -1; + res = ESOCK_STR_EINVAL; + } + + } else { + + *val = -1; + res = ESOCK_STR_EINVAL; + + } + + return res; +} +#endif + + + /* +++ encode the ip socket option MTU_DISCOVER +++ * The (ip) option can be provide in two ways: * @@ -7765,6 +7913,48 @@ void encode_ip_pmtudisc(ErlNifEnv* env, int val, ERL_NIF_TERM* eVal) +/* +++ encode the ipv6 socket option MTU_DISCOVER +++ + * The (ipv6) option can be provide in two ways: + * + * atom() | integer() + * + * If its one of the "known" values, it will be an atom: + * + * want | dont | do | probe + * + */ +#if defined(IPV6_MTU_DISCOVER) +static +void encode_ipv6_pmtudisc(ErlNifEnv* env, int val, ERL_NIF_TERM* eVal) +{ + switch (val) { + case IPV6_PMTUDISC_WANT: + *eVal = atom_want; + break; + + case IPV6_PMTUDISC_DONT: + *eVal = atom_dont; + break; + + case IPV6_PMTUDISC_DO: + *eVal = atom_do; + break; + + case IPV6_PMTUDISC_PROBE: + *eVal = atom_probe; + break; + + default: + *eVal = MKI(env, val); + break; + } + + return; +} +#endif + + + /* +++ decocde the native getopt option +++ * The option is in this case provide in the form of a two tuple: * diff --git a/erts/preloaded/ebin/socket.beam b/erts/preloaded/ebin/socket.beam Binary files differindex 7ab8b0b3c4..cb1c5fc815 100644 --- a/erts/preloaded/ebin/socket.beam +++ b/erts/preloaded/ebin/socket.beam diff --git a/erts/preloaded/src/socket.erl b/erts/preloaded/src/socket.erl index 41df672ef5..ead058c607 100644 --- a/erts/preloaded/src/socket.erl +++ b/erts/preloaded/src/socket.erl @@ -93,6 +93,7 @@ ip_mreq_source/0, ip_pmtudisc/0, ipv6_mreq/0, + ipv6_pmtudisc/0, msg_hdr/0 @@ -164,6 +165,8 @@ -type ipv6_mreq() :: #{multiaddr := ip6_address(), interface := non_neg_integer()}. +-type ipv6_pmtudisc() :: ip_pmtudisc(). + -type sockaddr_un() :: #{family := local, path := binary() | string()}. -type sockaddr_in4() :: #{family := inet, @@ -587,7 +590,7 @@ %% -define(SOCKET_OPT_IPV6_JOIN_GROUP, 15). %% -define(SOCKET_OPT_IPV6_LEAVE_GROUP, 16). -define(SOCKET_OPT_IPV6_MTU, 17). -%% -define(SOCKET_OPT_IPV6_MTU_DISCOVER, 18). +-define(SOCKET_OPT_IPV6_MTU_DISCOVER, 18). %% -define(SOCKET_OPT_IPV6_MULTICAST_HOPS, 19). %% -define(SOCKET_OPT_IPV6_MULTICAST_IF, 20). %% -define(SOCKET_OPT_IPV6_MULTICAST_LOOP, 21). @@ -2107,6 +2110,13 @@ enc_setopt_value(ipv6, hoplimit, V, _D, T, _P) V; enc_setopt_value(ipv6, mtu, V, _D, _T, _P) when is_integer(V) -> V; +enc_setopt_value(ipv6, mtu_discover, V, _D, _T, _P) + when (V =:= want) orelse + (V =:= dont) orelse + (V =:= do) orelse + (V =:= probe) orelse + is_integer(V) -> + V; enc_setopt_value(ipv6, v6only, V, _D, _T, _P) when is_boolean(V) -> V; enc_setopt_value(ipv6 = L, Opt, V, _D, _T, _P) -> @@ -2462,8 +2472,8 @@ enc_sockopt_key(ipv6 = L, leave_group = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ipv6 = _L, mtu = _Opt, _Dir, _D, _T, _P) -> ?SOCKET_OPT_IPV6_MTU; -enc_sockopt_key(ipv6 = L, mtu_discover = Opt, _Dir, _D, _T, _P) -> - not_supported({L, Opt}); +enc_sockopt_key(ipv6 = _L, mtu_discover = _Opt, _Dir, _D, _T, _P) -> + ?SOCKET_OPT_IPV6_MTU_DISCOVER; enc_sockopt_key(ipv6 = L, multicast_hops = Opt, _Dir, _D, _T, _P) -> not_supported({L, Opt}); enc_sockopt_key(ipv6 = L, multicast_if = Opt, _Dir, _D, T, _P) |