|| $name eq 'accesslog') {
$value = defined $value && $value =~ /^yes$/i ? 1
: defined $value && $value =~ /^no$/i ? 0
- : undef
+ : undef
;
if (!defined $value) {
config_error($line, 'ERR0102', $config);
}
elsif ( $name eq 'socketoption') {
$value = lc $value;
- # socketoption=OPTION,OPTION,OPTION
+ $value =~ s/ //g;
if (!defined $value) {
config_error($line, 'ERR0124', $config);
}
my @option_value = split /,/, $value;
- # OPTION:deferaccept,nodelay,cork,quickackon|quickackoff
+ # OPTION:transparent,deferaccept,nodelay,cork,quickackon|quickackoff
for my $option (@option_value) {
- if($option !~ /^deferaccept|nodelay|cork|quickackon|quickackoff$/) {
+ $option =~ s/ //g;
+ if($option !~ /^transparent|deferaccept|nodelay|cork|quickackon|quickackoff$/) {
config_error($line, 'ERR0124', $config);
}
}
designated.
-=item B<socketoption = ">I<OPTION,OPTION, ...>B<">
+=item B<socketoption = ">I<OPTION...>B<">
-An option of the socket used in VirtualService (TCP) is designated.
+An option of the socket used in VirtualService is designated.
The setting possible value is described.
-1.deferaccept
- In a listener socket of VirtualService, TCP_DEFER_ACCEPT setting.
+=over
+
+=item B<transparent>
+
+Set IP_TRANSPARENT option to the RealServer socket.
+
+=item B<deferaccept>
-2.nodelay
- In a socket for communication with Client in Session and RealServer, TCP_NODELAY setting.
+Set TCP_DEFER_ACCEPT option to the listener socket of VirtualService.
-3.cork
- In a socket for communication with Client in Session and RealServer, TCP_CORK setting.
+=item B<nodelay>
-4.quickackon or quickackoff
- In a socket for communication with Client in Session and RealServer, TCP_QUICKACK setting.
+Set TCP_NODELAY option to the Client and RealServer socket.
-example:
- socketoption=deferaccept,nodelay,quickackoff
+=item B<cork>
+
+Set TCP_CORK option to the Client and RealServer socket.
+
+=item B<quickackon> or B<quickackoff>
+
+Set or unset TCP_QUICKACK option to the Client and RealServer socket.
+
+=back
-=item B<accesslog = ">I<ACCESSLOG_ROTATE_TYPE>B<">
+=item B<accesslog = >[B<yes>|B<no>]
-A presence of access log output is established.
-yes: outputs/no: doesn't output.
+If B<yes>, then output client access log. The default is B<no>.
-=item B<accesslog_rotate_type = date>|B<size>|B<datesize>
+=item B<accesslog_rotate_type = >[B<date>|B<size>|B<datesize>]
-The rotation type designates "date" "size" "datesize".
+B<date> means rotate access log with the specified date/time. B<size> means rotate access log when that file size exceeds the specified size. B<datesize> means both B<date> and B<size>.
=item B<accesslog_rotate_max_backup_index = >I<n>
-The maximum number of back-up file is designated.
+Maximum number of backup files.
=item B<accesslog_rotate_max_filesize = > I<n>[B<K>|B<M>|B<G>]
-The most large size of log is designated.
-When "size" and "datesize" are set as accesslog_rotate_type, it becomes indispensable. K(kilo), M(mega) and G(giga) unit are available.
+Threshold file size of access log when B<accesslog_rotate_type> is set to B<size> or B<datesize>. B<K>(kilo), B<M>(mega) and B<G>(giga) units are available.
-=item B<accesslog_rotate_rotation_timing = year>|B<month>|B<week>|B<date>|B<hour>
+=item B<accesslog_rotate_rotation_timing = >[B<year>|B<month>|B<week>|B<date>|B<hour>]
-It's designated at the timing of a rotation.
-When "date" and "datesize" are set as accesslog_rotate_type, it becomes indispensable.
+Rotate timing type when B<accesslog_rotate_type> is set to B<date> or B<datesize>.
=item B<accesslog_rotate_rotation_timing_value = ">I<rotation_timing_value>B<">
-When "year" was designated as accesslog_rotate_rotation_timing.
- FORMAT: "MM/dd hh:mm" MM(month) dd(day) hh(hour):mm(minute)
+Rotate timing. The formats are different by B<accesslog_rotate_rotation_timing> setting.
-When "month" was designated as accesslog_rotate_rotation_timing.
- FORMAT: "dd hh:mm" dd(day) hh(hour):mm(minute)
+=over
+
+=item B<accesslog_rotate_rotation_timing=year>
+
+FORMAT: B<"MM/dd HH:mm">
+
+=item B<accesslog_rotate_rotation_timing=month>
+
+FORMAT: B<"dd HH:mm">
-When "week" was designated as accesslog_rotate_rotation_timing.
- FORMAT: "<week> hh:mm" sun|mon|tue|wed|thu|fri|sat(week) hh(hour):mm(minute)"
+=item B<accesslog_rotate_rotation_timing=week>
-When "date" was designated as accesslog_rotate_rotation_timing.
- FORMAT: "hh:mm" hh(hour):mm(minute)
+FORMAT: B<">[B<sun>|B<mon>|B<tue>|B<wed>|B<thu>|B<fri>|B<sat>] B<HH:mm">
-When "hour" was designated as accesslog_rotate_rotation_timing.
- FORMAT: "mm" mm(minute)
+=item B<accesslog_rotate_rotation_timing=date>
+
+FORMAT: B<"HH:mm">
+
+=item B<accesslog_rotate_rotation_timing=hour>
+
+FORMAT: B<"mm">
+
+=back
=back
{
//! tcp_socket_option
struct tcp_socket_option_info {
+ //! IP_TRANSPARENT (false:not set,true:set option)
+ bool transparent_opt;
+ //! IP_TRANSPARENT option value (false:off,true:on)
+ bool transparent_val;
//! TCP_NODELAY (false:not set,true:set option)
bool nodelay_opt;
//! TCP_NODELAY option value (false:off,true:on)
std::string protocol_module_for_indication_options;
std::string access_log_rotate_key_info;
std::string access_log_rotate_verbose_info;
+ int socket_option_ip_transparent;
int socket_option_tcp_defer_accept;
int socket_option_tcp_nodelay;
int socket_option_tcp_cork;
throughput_upstream(0ULL),
throughput_downstream(0ULL),
access_log_flag(0),
+ socket_option_ip_transparent(0),
socket_option_tcp_defer_accept(0),
socket_option_tcp_nodelay(0),
socket_option_tcp_cork(0),
protocol_module_for_indication_options(in.protocol_module_for_indication_options),
access_log_rotate_key_info(in.access_log_rotate_key_info),
access_log_rotate_verbose_info(in.access_log_rotate_verbose_info),
+ socket_option_ip_transparent(in.socket_option_ip_transparent),
socket_option_tcp_defer_accept(in.socket_option_tcp_defer_accept),
socket_option_tcp_nodelay(in.socket_option_tcp_nodelay),
socket_option_tcp_cork(in.socket_option_tcp_cork),
protocol_module_for_indication_options = in.protocol_module_for_indication_options;
access_log_rotate_key_info = in.access_log_rotate_key_info;
access_log_rotate_verbose_info = in.access_log_rotate_verbose_info;
+ socket_option_ip_transparent = in.socket_option_ip_transparent;
socket_option_tcp_defer_accept = in.socket_option_tcp_defer_accept;
socket_option_tcp_nodelay = in.socket_option_tcp_nodelay;
socket_option_tcp_cork = in.socket_option_tcp_cork;
elem1.protocol_module_for_indication_options == elem2.protocol_module_for_indication_options &&
elem1.access_log_rotate_key_info == elem2.access_log_rotate_key_info &&
elem1.access_log_rotate_verbose_info == elem2.access_log_rotate_verbose_info &&
+ elem1.socket_option_ip_transparent == elem2.socket_option_ip_transparent &&
elem1.socket_option_tcp_defer_accept == elem2.socket_option_tcp_defer_accept &&
elem1.socket_option_tcp_nodelay == elem2.socket_option_tcp_nodelay &&
elem1.socket_option_tcp_cork == elem2.socket_option_tcp_cork &&
elem1.protocol_module_for_indication_options == elem2.protocol_module_for_indication_options &&
elem1.access_log_rotate_key_info == elem2.access_log_rotate_key_info &&
elem1.access_log_rotate_verbose_info == elem2.access_log_rotate_verbose_info &&
+ elem1.socket_option_ip_transparent == elem2.socket_option_ip_transparent &&
elem1.socket_option_tcp_defer_accept == elem2.socket_option_tcp_defer_accept &&
elem1.socket_option_tcp_nodelay == elem2.socket_option_tcp_nodelay &&
elem1.socket_option_tcp_cork == elem2.socket_option_tcp_cork &&
"protocol_module_for_indication_options=%s: "
"access_log_rotate_key_info=%s: "
"access_log_rotate_verbose_info=%s: "
+ "socket_option_ip_transparent=%d: "
"socket_option_tcp_defer_accept=%d: "
"socket_option_tcp_nodelay=%d: "
"socket_option_tcp_cork=%d: "
% elem.protocol_module_for_indication_options
% elem.access_log_rotate_key_info
% elem.access_log_rotate_verbose_info
+ % elem.socket_option_ip_transparent
% elem.socket_option_tcp_defer_accept
% elem.socket_option_tcp_nodelay
% elem.socket_option_tcp_cork
ar &protocol_module_for_indication_options;
ar &access_log_rotate_key_info;
ar &access_log_rotate_verbose_info;
+ ar &socket_option_ip_transparent;
ar &socket_option_tcp_defer_accept;
ar &socket_option_tcp_nodelay;
ar &socket_option_tcp_cork;
return false;
}
+#ifdef IP_TRANSPARENT
+ bool is_set_transparent = false;
+#endif
bool is_set_defer_accept = false;
bool is_set_nodelay = false;
bool is_set_cork = false;
bool is_set_quickack = false;
+ request.vs_element.socket_option_ip_transparent = 0;
request.vs_element.socket_option_tcp_defer_accept = 0;
request.vs_element.socket_option_tcp_nodelay = 0;
request.vs_element.socket_option_tcp_cork = 0;
boost::split(socket_options, socket_option_string, boost::algorithm::is_any_of(","));
BOOST_FOREACH(std::string option, socket_options) {
- if (option == "deferaccept") {
+ if (option == "transparent") {
+#ifdef IP_TRANSPARENT
+ if (!is_set_transparent) {
+ is_set_transparent = true;
+ request.vs_element.socket_option_ip_transparent = 1;
+ } else {
+ // transparent is duplicated
+ std::stringstream buf;
+ buf << "socket option transparent is duplicated.";
+ l7vsadm_err.setter(true, buf.str());
+ Logger::putLogError(LOG_CAT_L7VSADM_PARSE, /*XXX*/999, buf.str(), __FILE__, __LINE__);
+ return false;
+ }
+#else
+ std::stringstream buf;
+ buf << "socket option transparent(IP_TRANSPARENT) not supported on this platform";
+ l7vsadm_err.setter(true, buf.str());
+ Logger::putLogError(LOG_CAT_L7VSADM_PARSE, /*XXX*/999, buf.str(), __FILE__, __LINE__);
+ return false;
+#endif
+ } else if (option == "deferaccept") {
if (!is_set_defer_accept) {
is_set_defer_accept = true;
request.vs_element.socket_option_tcp_defer_accept = 1;
" --qos-up -Q QoSval-up QoS Threshold(bps) set to real server direction\n"
" --qos-down -q QoSval-down QoS Threshold(bps) set to client direction\n"
" --ssl -z ssl-config-file SSL configuration file(Use SSL)\n"
+#ifdef IP_TRANSPARENT
+ " --sockopt -O socket-option transparent,deferaccept,nodelay,cork,quickackon or quickackoff set to socket option\n"
+#else
" --sockopt -O socket-option deferaccept,nodelay,cork,quickackon or quickackoff set to socket option\n"
+#endif
" --access-log -L access-log-flag access log flag 0(none) or 1(output)\n"
" --access-log-name -a access-log-file access log file\n"
" [logrotate-args]\n"
} else {
tcp_socket_ptr new_socket(new tcp_socket(io, socket_opt_info));
boost::system::error_code ec;
+ if (socket_opt_info.transparent_opt) {
+#ifdef IP_TRANSPARENT
+ int val = socket_opt_info.transparent_val;
+ size_t len = sizeof(val);
+ // set IP_TRANSPARENT
+ boost::asio::detail::socket_ops::setsockopt(
+ new_socket->get_socket(), SOL_IP, IP_TRANSPARENT, &val, len, ec);
+ if (unlikely(ec)) {
+ //ERROR
+ Logger::putLogError(LOG_CAT_L7VSD_SESSION, /*XXX*/999,
+ "socket option(IP_TRANSPARENT) set failed",
+ __FILE__, __LINE__);
+ } else {
+ endpoint client_endpoint = up_thread_data_client_side.get_endpoint();
+ // bind client address
+ new_socket->get_socket().bind(client_endpoint, ec);
+ if (unlikely(ec)) {
+ Logger::putLogError(LOG_CAT_L7VSD_SESSION, /*XXX*/999,
+ "bind client addr failed",
+ __FILE__, __LINE__);
+ }
+ }
+#else
+ Logger::putLogError(LOG_CAT_L7VSD_SESSION, /*XXX*/999,
+ "setsockopt(IP_TRANSPARENT) not supported on this platform",
+ __FILE__, __LINE__);
+#endif
+ }
bool bres = new_socket->connect(server_endpoint, ec);
if (likely(bres)) {
{
endpoint sorry_endpoint = up_thread_data_dest_side.get_endpoint();
boost::system::error_code ec;
+ if (socket_opt_info.transparent_opt) {
+#ifdef IP_TRANSPARENT
+ int val = socket_opt_info.transparent_val;
+ size_t len = sizeof(val);
+ // set IP_TRANSPARENT
+ boost::asio::detail::socket_ops::setsockopt(
+ sorryserver_socket.second->get_socket(), SOL_IP, IP_TRANSPARENT, &val, len, ec);
+ if (unlikely(ec)) {
+ //ERROR
+ Logger::putLogError(LOG_CAT_L7VSD_SESSION, /*XXX*/999,
+ "socket option(IP_TRANSPARENT) set failed",
+ __FILE__, __LINE__);
+ } else {
+ endpoint client_endpoint = up_thread_data_client_side.get_endpoint();
+ // bind client address
+ sorryserver_socket.second->get_socket().bind(client_endpoint, ec);
+ if (unlikely(ec)) {
+ Logger::putLogError(LOG_CAT_L7VSD_SESSION, /*XXX*/999,
+ "bind client addr failed",
+ __FILE__, __LINE__);
+ }
+ }
+#else
+ Logger::putLogError(LOG_CAT_L7VSD_SESSION, /*XXX*/999,
+ "setsockopt(IP_TRANSPARENT) not supported on this platform",
+ __FILE__, __LINE__);
+#endif
+ }
bool bres = sorryserver_socket.second->connect(sorry_endpoint, ec);
UP_THREAD_FUNC_TYPE_TAG func_tag;
if (likely(bres)) {
}
// socket option check & set
- //! is set option TCP_DEFER_ACCEPT
+ //! IP_TRANSPARENT (false:not set,true:set option)
+ set_sock_opt.transparent_opt = false;
+ //! TCP_DEFER_ACCEPT option value (false:off,true:on)
+ set_sock_opt.transparent_val = false;
+ //! TCP_DEFER_ACCEPT (false:not set,true:set option)
defer_accept_opt = false;
//! TCP_DEFER_ACCEPT option value
defer_accept_val = 0;
-
//! TCP_NODELAY (false:not set,true:set option)
set_sock_opt.nodelay_opt = false;
//! TCP_NODELAY option value (false:off,true:on)
set_sock_opt.quickack_val = false;
// set socket option
+ if (element.socket_option_ip_transparent != 0) {
+ set_sock_opt.transparent_opt = true;
+ if (element.socket_option_ip_transparent == 1) {
+ set_sock_opt.transparent_val = true;
+ }
+ }
+
if (element.socket_option_tcp_defer_accept != 0) {
defer_accept_opt = true;
if (element.socket_option_tcp_defer_accept == 1) {
}
if (element.socket_option_tcp_quickack != 0) {
-
set_sock_opt.quickack_opt = true;
if (element.socket_option_tcp_quickack == 1) {
set_sock_opt.quickack_val = true;
//----Debug log----------------------------------------------------------------------
if (unlikely(LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSD_VIRTUALSERVICE))) {
boost::format formatter("set_socket_option"
+ " transparent_opt[%s] transparent_val[%s]"
" defer_accept_opt[%s] defer_accept_val[%d]"
" nodelay_opt[%s] nodelay_val[%s]"
" cork_opt[%s] cork_val[%s]"
" quickack_opt[%s]" "quickack_val[%s]");
- formatter % (defer_accept_opt ? "true" : "false") % defer_accept_val
+ formatter % (set_sock_opt.transparent_opt ? "true" : "false") % (set_sock_opt.transparent_val ? "true" : "false")
+ % (defer_accept_opt ? "true" : "false") % defer_accept_val
% (set_sock_opt.nodelay_opt ? "true" : "false") % (set_sock_opt.nodelay_val ? "true" : "false")
% (set_sock_opt.cork_opt ? "true" : "false") % (set_sock_opt.cork_val ? "true" : "false")
% (set_sock_opt.quickack_opt ? "true" : "false") % (set_sock_opt.quickack_val ? "true" : "false");