Permalink
Browse files

IPv6 support, first try (TSUN-202)

  • Loading branch information...
1 parent 9aa00eb commit 19df298f4121d885665638ad20d3730b6cfe0959 @nniclausse nniclausse committed Dec 1, 2011
View
@@ -35,6 +35,7 @@ A distributed multi-protocol load testing tool.
<arg><option>-m</option> filename</arg>
<arg><option>-r</option> command</arg>
<arg><option>-v</option></arg>
+ <arg><option>-6</option></arg>
<arg><option>-h</option></arg>
<arg>start|stop|debug|status</arg>
</cmdsynopsis>
@@ -153,6 +154,12 @@ A distributed multi-protocol load testing tool.
</listitem>
</varlistentry>
<varlistentry>
+ <term><option>-6</option></term>
+ <listitem>
+ <para> Use IPv6 for tsung internal communications</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>-h</option></term>
<listitem>
<para> Show usage</para>
@@ -96,7 +96,8 @@
<!--CUT DEF section 1 --><H1 ALIGN=center>Tsung User’s manual</H1><DIV CLASS="center">
<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=1><TR><TD ALIGN=left NOWRAP bgcolor="#F2F2F2"> Version:</TD><TD ALIGN=left NOWRAP>1.4.2</TD></TR>
-<TR><TD ALIGN=left NOWRAP bgcolor="#F2F2F2"> Date :</TD><TD ALIGN=left NOWRAP>November 29, 2011</TD></TR>
+<TR><TD ALIGN=left NOWRAP bgcolor="#F2F2F2"> Date :</TD><TD ALIGN=left NOWRAP>December
+ 1, 2011</TD></TR>
</TABLE>
</DIV><!--TOC section Contents-->
<H2 CLASS="section"><!--SEC ANCHOR -->Contents</H2><!--SEC END --><UL CLASS="toc"><LI CLASS="li-toc">
@@ -487,6 +488,7 @@ <H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc19">3.4</A>  Running</H3
-F use long names (FQDN) for erlang nodes
-w warmup delay (default is 10 sec)
-v print version information and exit
+ -6 use IPv6 for tsung internal communications
-h display this help and exit
</PRE></TD></TR>
</TABLE></TD><TD BGCOLOR=black COLSPAN="1"><TABLE CELLSPACING="1" CELLPADDING=0 BORDER=0><TR><TD>
@@ -892,7 +894,9 @@ <H4 CLASS="subsubsection"><!--SEC ANCHOR --><A NAME="htoc41">6.2.1</A>  Basic
</TABLE><P>This will start the load on the same host and on the same Erlang
virtual machine as the controller.</P><P>The server is the entry point into the cluster (<B>New in 1.2.0:</B>
if several servers are defined, a round robin algorithm is used to
-choose the server).</P><!--TOC subsubsection Advanced setup-->
+choose the server).</P><P><TT>Type</TT> can be <FONT COLOR=purple>tcp</FONT>, <FONT COLOR=purple>ssl</FONT> or
+<FONT COLOR=purple>udp</FONT> (for IPv6, use <FONT COLOR=purple>tcp6</FONT>, <FONT COLOR=purple>ssl6</FONT> or
+<FONT COLOR=purple>udp6</FONT> ; only available in version <B>1.4.2</B> and newer)</P><!--TOC subsubsection Advanced setup-->
<H4 CLASS="subsubsection"><!--SEC ANCHOR --><A NAME="htoc42">6.2.2</A>  Advanced setup</H4><!--SEC END --><P>The next example is more complex, and use several features for
advanced distributed testing:</P><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0><TR><TD><TABLE BORDER=0 CELLPADDING=0
CELLSPACING=0><TR><TD BGCOLOR=black COLSPAN="3"><TABLE CELLSPACING="1" CELLPADDING=0 BORDER=0><TR><TD>
View
@@ -366,6 +366,7 @@ \subsection{Running}
-F use long names (FQDN) for erlang nodes
-w warmup delay (default is 10 sec)
-v print version information and exit
+ -6 use IPv6 for tsung internal communications
-h display this help and exit
\end{Verbatim}
@@ -758,6 +759,10 @@ \subsubsection{Basic setup}
if several servers are defined, a round robin algorithm is used to
choose the server).
+\varname{Type} can be \userinput{tcp}, \userinput{ssl} or
+\userinput{udp} (for IPv6, use \userinput{tcp6}, \userinput{ssl6} or
+\userinput{udp6} ; only available in version \strong{1.4.2} and newer)
+
\subsubsection{Advanced setup}
The next example is more complex, and use several features for
@@ -27,10 +27,31 @@
-include("ts_profile.hrl").
-include("ts_http.hrl").
+-include("ts_config.hrl").
-include_lib("eunit/include/eunit.hrl").
test()->ok.
+ipv6_url_test() ->
+ URL=ts_config_http:parse_URL("http://[2178:2:5:0:28f:0:3]:8080/toto.php?titi=[43]"),
+ ?assertMatch(#url{path="/toto.php",port=8080,host="2178:2:5:0:28f:0:3",scheme=http}, URL).
+
+ipv6_url2_test() ->
+ S=ts_config_http:server_to_url(#server{host="2178:2:5:0:28f:0:3",port=80,type=gen_tcp} ),
+ ?assertEqual("http://[2178:2:5:0:28f:0:3]", S).
+
+ipv6_url3_test() ->
+ S=ts_config_http:server_to_url(#server{host="[2178:2:5:0:28f:0:3]",port=80,type=gen_tcp} ),
+ ?assertEqual("http://[2178:2:5:0:28f:0:3]", S).
+
+ipv6_url4_test() ->
+ S=ts_config_http:server_to_url(#server{host="2178:2:5:0:28f:0:3",port=8080,type=gen_tcp} ),
+ ?assertEqual("http://[2178:2:5:0:28f:0:3]:8080", S).
+
+ipv4_url_test() ->
+ URL=ts_config_http:parse_URL("http://127.0.0.1:8080/"),
+ ?assertMatch(#url{path="/",port=8080,host="127.0.0.1",scheme=http}, URL).
+
subst_url_test() ->
DynVars=ts_dynvars:new('image', "/images/my image with spaces.png"),
Req=ts_http:subst(#http_request{url="%%_image%%"}, DynVars),
@@ -45,10 +66,22 @@ subst_redirect_test()->
DynVars=ts_dynvars:new(redirect,"http://erlang.org/bidule/truc"),
{Req,_}=ts_http:add_dynparams(true,#dyndata{proto=Proto,dynvars=DynVars},
#http_request{url=URL},
- {"erlang.org",80}),
+ {"erlang.org",80,gen_tcp}),
Str="GET /bidule/truc HTTP/1.1\r\nHost: erlang.org\r\nUser-Agent: Firefox\r\nCookie: toto=bar\r\n\r\n",
{Res,_}=ts_http:get_message(Req,#state_rcv{}),
- ?assertEqual(Str, binary_to_list(Res)).
+ ?assertMatch(Str, binary_to_list(Res)).
+
+subst_redirect_proto_test()->
+ myset_env(),
+ URL="%%_redirect%%",
+ Cookie="toto=bar; path=/; domain=erlang.org",
+ Cookies=ts_http_common:add_new_cookie(Cookie,"erlang.org",[]),
+ Proto=#http_dyndata{cookies=Cookies,user_agent="Firefox"},
+ DynVars=ts_dynvars:new(redirect,"http://erlang.org/bidule/truc"),
+ Rep=ts_http:add_dynparams(true,#dyndata{proto=Proto,dynvars=DynVars},
+ #http_request{url=URL},
+ {"erlang.org",80,gen_tcp6}),
+ ?assertMatch({_,{"erlang.org",80,gen_tcp6}}, Rep).
cookie_subdomain_test()->
myset_env(),
@@ -59,7 +92,7 @@ cookie_subdomain_test()->
DynVars=ts_dynvars:new(),
Req=ts_http:add_dynparams(false,#dyndata{proto=Proto,dynvars=DynVars},
#http_request{url=URL},
- {"www.domain.org",80}),
+ {"www.domain.org",80,gen_tcp}),
Str="GET /bidule/truc HTTP/1.1\r\nHost: www.domain.org:80\r\nUser-Agent: Firefox\r\nCookie: toto=bar\r\n\r\n",
{Res,_}=ts_http:get_message(Req,#state_rcv{}),
?assertEqual(Str, binary_to_list(Res)).
@@ -73,7 +106,7 @@ cookie_dotdomain_test()->
DynVars=ts_dynvars:new(),
Req=ts_http:add_dynparams(false,#dyndata{proto=Proto,dynvars=DynVars},
#http_request{url=URL},
- {"www.domain.org",80}),
+ {"www.domain.org",80, gen_tcp}),
Str="GET /bidule/truc HTTP/1.1\r\nHost: www.domain.org:80\r\nUser-Agent: Firefox\r\nCookie: toto=bar\r\n\r\n",
{Res,_}=ts_http:get_message(Req,#state_rcv{}),
?assertEqual(Str, binary_to_list(Res)).
@@ -138,7 +171,7 @@ add_cookie_samekey_nodomain_req_test()->
DynVars=ts_dynvars:new(),
Req=ts_http:add_dynparams(false,#dyndata{proto=Proto,dynvars=DynVars},
#http_request{url=URL},
- {"www.foobar.net",80}),
+ {"www.foobar.net",80, gen_tcp}),
Str="GET /bidule/truc HTTP/1.1\r\nHost: www.foobar.net:80\r\nUser-Agent: Firefox\r\nCookie: RMID=42\r\n\r\n",
{Res,_}=ts_http:get_message(Req,#state_rcv{}),
?assertEqual(Str, binary_to_list(Res)).
@@ -648,7 +648,7 @@ handle_next_request(Request, State) ->
case Type:add_dynparams(Request#ts_request.subst,
State#state_rcv.dyndata,
Request#ts_request.param,
- {PrevHost, PrevPort}) of
+ {PrevHost, PrevPort, PrevProto}) of
{Par, NewServer} -> % substitution has changed server setup
?DebugF("Dynparam, new server: ~p~n",[NewServer]),
{Par, NewServer};
@@ -823,7 +823,7 @@ reconnect(none, ServerName, Port, {Protocol, Proto_opts}, {IP,0}) ->
reconnect(none, ServerName, Port, {Protocol, Proto_opts}, {IP,CPort, Try}) when is_integer(CPort)->
?DebugF("Try to (re)connect to: ~p:~p from ~p using protocol ~p~n",
[ServerName,Port,IP,Protocol]),
- Opts = protocol_options(Protocol, Proto_opts) ++ [{ip, IP},{port,CPort}],
+ Opts = protocol_options(Protocol, Proto_opts) ++ socket_opts(IP, CPort, Protocol),
Before= now(),
case connect(Protocol,ServerName, Port, Opts) of
{ok, Socket} ->
@@ -871,14 +871,27 @@ reconnect(Socket, _Server, _Port, _Protocol, _IP) ->
{ok, Socket}.
+%% set options for local socket ip/ports
+socket_opts({0,0,0,0}, CPort, Proto) when Proto==gen_tcp6 orelse Proto==ssl6 orelse Proto==gen_udp6 ->
+ %% the config server was not aware if we are using ipv6 or ipv4,
+ %% and it set the local IP to be default one; we need to change it
+ %% for ipv6
+ [{ip, {0,0,0,0,0,0,0,0}},{port,CPort}];
+socket_opts(IP, CPort, _)->
+ [{ip, IP},{port,CPort}].
+
%%----------------------------------------------------------------------
%% Func: send/5
%% Purpose: wrapper function for send
-%% Return: ok | {error, Reason}
+%% Return: ok | {error, Reason}
%%----------------------------------------------------------------------
-send(gen_tcp,Socket,Message,_,_) -> gen_tcp:send(Socket,Message);
-send(ssl,Socket,Message,_,_) -> ssl:send(Socket,Message);
-send(gen_udp,Socket,Message,Host,Port) ->gen_udp:send(Socket,Host,Port,Message);
+send(gen_tcp,Socket,Message,_,_) -> gen_tcp:send(Socket,Message);
+send(ssl,Socket,Message,_,_) -> ssl:send(Socket,Message);
+send(gen_udp,Socket,Message,Host,Port) ->gen_udp:send(Socket,Host,Port,Message);
+% ipv6
+send(gen_tcp6,Socket,Message,_,_) -> gen_tcp:send(Socket,Message);
+send(ssl6,Socket,Message,_,_) -> ssl:send(Socket,Message);
+send(gen_udp6,Socket,Message,Host,Port) ->gen_udp:send(Socket,Host,Port,Message);
send(erlang,Pid,Message,_,_) ->
Pid ! Message,
ok.
@@ -887,10 +900,13 @@ send(erlang,Pid,Message,_,_) ->
%% Func: connect/4
%% Return: {ok, Socket} | {error, Reason}
%%----------------------------------------------------------------------
-connect(gen_tcp,Server, Port, Opts) -> gen_tcp:connect(Server, Port, Opts);
-connect(ssl,Server, Port,Opts) -> ssl:connect(Server, Port, Opts);
-connect(gen_udp,_Server, _Port, Opts)-> gen_udp:open(0,Opts);
-connect(erlang,Server,Port,Opts) ->
+connect(gen_tcp,Server, Port, Opts) -> gen_tcp:connect(Server, Port, Opts);
+connect(ssl,Server, Port,Opts) -> ssl:connect(Server, Port, Opts);
+connect(gen_udp,_Server, _Port, Opts) -> gen_udp:open(0,Opts);
+connect(gen_tcp6,Server, Port, Opts) -> gen_tcp:connect(Server, Port, Opts);
+connect(ssl6,Server, Port,Opts) -> ssl:connect(Server, Port, Opts);
+connect(gen_udp6,_Server, _Port, Opts)-> gen_udp:open(0,Opts);
+connect(erlang,Server,Port,Opts) ->
Pid=spawn_link(ts_erlang,client,[self(),Server,Port,Opts]),
{ok, Pid}.
@@ -899,19 +915,25 @@ connect(erlang,Server,Port,Opts) ->
%% Func: protocol_options/1
%% Purpose: set connection's options for the given protocol
%%----------------------------------------------------------------------
+protocol_options(ssl6,Val) ->
+ [inet6]++protocol_options(ssl,Val);
protocol_options(ssl,#proto_opts{ssl_ciphers=negociate}) ->
[binary, {active, once} ];
protocol_options(ssl,#proto_opts{ssl_ciphers=Ciphers}) ->
?DebugF("cipher is ~p~n",[Ciphers]),
[binary, {active, once}, {ciphers, Ciphers} ];
+protocol_options(gen_tcp6,Val) ->
+ [inet6]++protocol_options(gen_tcp,Val);
protocol_options(gen_tcp,#proto_opts{tcp_rcv_size=Rcv, tcp_snd_size=Snd}) ->
[binary,
{active, once},
{recbuf, Rcv},
{sndbuf, Snd},
{keepalive, true} %% FIXME: should be an option
];
+protocol_options(gen_udp6,Val) ->
+ [inet6]++protocol_options(gen_udp,Val);
protocol_options(gen_udp,#proto_opts{udp_rcv_size=Rcv, udp_snd_size=Snd}) ->
[binary,
{active, once},
View
@@ -163,7 +163,7 @@ parse_config(Element, Conf) ->
%%----------------------------------------------------------------------
add_dynparams(false, DynData, Param, HostData) ->
add_dynparams(DynData#dyndata.proto, Param, HostData);
-add_dynparams(true, DynData, OldReq=#http_request{url=OldUrl}, HostData) ->
+add_dynparams(true, DynData, OldReq=#http_request{url=OldUrl}, HostData={PrevHost, PrevPort, PrevProto}) ->
Req = subst(OldReq, DynData#dyndata.dynvars),
case Req#http_request.url of
OldUrl ->
@@ -174,13 +174,13 @@ add_dynparams(true, DynData, OldReq=#http_request{url=OldUrl}, HostData) ->
NewPort = ts_config_http:set_port(URL),
NewReq = add_dynparams(DynData#dyndata.proto,
Req#http_request{host_header=undefined},
- {URL#url.host, NewPort, URL#url.scheme}), % add scheme
+ {URL#url.host, NewPort, PrevProto, URL#url.scheme}), % add scheme
case OldUrl of
"http"++_ -> % old url absolute: useproxy must be true
NewReq#http_request{url="http"++Rest};
_ ->
NewUrl=ts_config_http:set_query(URL),
- {NewReq#http_request{url=NewUrl}, {URL#url.host, NewPort,ts_config_http:set_scheme(URL#url.scheme)}}
+ {NewReq#http_request{url=NewUrl}, {URL#url.host, NewPort,ts_config_http:set_scheme({URL#url.scheme,PrevProto})}}
end;
_ -> % Same host:port
add_dynparams(DynData#dyndata.proto, Req, HostData)
@@ -189,13 +189,13 @@ add_dynparams(true, DynData, OldReq=#http_request{url=OldUrl}, HostData) ->
%% Function: add_dynparams/3
add_dynparams(DynData,Param=#http_request{host_header=undefined}, HostData )->
Header = case HostData of
- {Host,80, http}->
+ {Host,80, _,http}->
Host;
- {Host,443, https}->
+ {Host,443,_,https}->
Host;
- {Host,Port,_} ->
+ {Host,Port,_,_} ->
Host++":"++ integer_to_list(Port);
- {Host,Port} ->
+ {Host,Port,_Proto} ->
Host++":"++ integer_to_list(Port)
end,
?DebugF("set host header dynamically: ~s~n",[Header]),
@@ -239,9 +239,12 @@ mkey1search(List, Key) ->
%% close socket if it exists
close_socket(_Protocol, none) -> ok;
-close_socket(gen_tcp, Socket)-> gen_tcp:close(Socket);
-close_socket(ssl, Socket) -> ssl:close(Socket);
-close_socket(gen_udp, Socket)-> gen_udp:close(Socket).
+close_socket(gen_tcp, Socket) -> gen_tcp:close(Socket);
+close_socket(gen_tcp6, Socket)-> gen_tcp:close(Socket);
+close_socket(ssl, Socket) -> ssl:close(Socket);
+close_socket(ssl6, Socket) -> ssl:close(Socket);
+close_socket(gen_udp, Socket) -> gen_udp:close(Socket);
+close_socket(gen_udp6, Socket)-> gen_udp:close(Socket).
%%----------------------------------------------------------------------
%% datestr/0
@@ -288,6 +291,12 @@ erl_system_args(extended)->
" -kernel inetrc '"++ InetRcFile ++ "'" ;
_ -> " "
end,
+ Proto = case init:get_argument(proto_dist) of
+ {ok,[["inet6_tcp"]]}->
+ ?LOG("IPv6 used for erlang distribution~n",?NOTICE),
+ " -proto_dist inet6_tcp " ;
+ _ -> " "
+ end,
ListenMin = case application:get_env(kernel,inet_dist_listen_min) of
undefined -> "";
{ok, Min} -> " -kernel inet_dist_listen_min " ++ integer_to_list(Min)++ " "
@@ -302,7 +311,7 @@ erl_system_args(extended)->
"5.3" ++ _Tail -> " +Mea r10b ";
_ -> " "
end,
- lists:append([BasicArgs, Shared, Hybrid, Smp, Mea, Inet, Threads,ProcessMax,ListenMin,ListenMax]).
+ lists:append([BasicArgs, Shared, Hybrid, Smp, Mea, Inet, Proto, Threads,ProcessMax,ListenMin,ListenMax]).
%%----------------------------------------------------------------------
%% setsubdir/1
@@ -525,6 +534,8 @@ spawn_par(Fun, PidFrom, Args) ->
%%----------------------------------------------------------------------
inet_setopts(_, none, _) -> %socket was closed before
none;
+inet_setopts(ssl6, Socket, Opts) ->
+ inet_setopts(ssl, Socket, Opts);
inet_setopts(ssl, Socket, Opts) ->
case ssl:setopts(Socket, Opts) of
ok ->
@@ -535,6 +546,10 @@ inet_setopts(ssl, Socket, Opts) ->
?LOGF("Error while setting ssl options ~p ~p ~n", [Opts, Error], ?ERR),
none
end;
+inet_setopts(gen_tcp6, Socket, Opts)->
+ inet_setopts(gen_tcp, Socket, Opts);
+inet_setopts(gen_udp6, Socket, Opts)->
+ inet_setopts(gen_udp, Socket, Opts);
inet_setopts(_Type, Socket, Opts)->
case inet:setopts(Socket, Opts) of
ok ->
@@ -102,12 +102,7 @@ parse(Element = #xmlElement{parents = [], attributes=Attrs}, Conf=#config{}) ->
parse(Element = #xmlElement{name=server, attributes=Attrs}, Conf=#config{servers=ServerList}) ->
Server = getAttr(Attrs, host),
Port = getAttr(integer, Attrs, port),
- Type = case getAttr(Attrs, type) of
- "ssl" -> ssl;
- "tcp" -> gen_tcp;
- "udp" -> gen_udp;
- "erlang" -> erlang
- end,
+ Type = set_net_type(getAttr(Attrs, type)),
lists:foldl(fun parse/2,
Conf#config{servers = [#server{host=Server,
@@ -555,12 +550,7 @@ parse( #xmlElement{name=change_type, attributes=Attrs},
Port = getAttr(integer, Attrs, port),
Store = getAttr(atom, Attrs, store, false),
Restore = getAttr(atom, Attrs, restore, false),
- PType = case getAttr(Attrs, server_type) of
- "ssl" -> ssl;
- "tcp" -> gen_tcp;
- "udp" -> gen_udp;
- "erlang" -> erlang
- end,
+ PType = set_net_type(getAttr(Attrs, server_type)),
SessType=case Conf#config.main_sess_type == CType of
false -> CurS#session.type;
true -> CType % back to the main type
@@ -998,3 +988,9 @@ read_stdio(eof, Data)->
read_stdio(Data,Acc) ->
read_stdio(io:get_line(""),[Acc,Data]).
+set_net_type("tcp") -> gen_tcp;
+set_net_type("tcp6") -> gen_tcp6;
+set_net_type("udp") -> gen_udp;
+set_net_type("udp6") -> gen_udp6;
+set_net_type("ssl") -> ssl;
+set_net_type("ssl6") -> ssl6.
Oops, something went wrong.

0 comments on commit 19df298

Please sign in to comment.