OSDN Git Service

Implement client source-IP transparent mode.
authortanuma <tanuma@1ed66053-1c2d-0410-8867-f7571e6e31d3>
Thu, 17 Jun 2010 10:41:22 +0000 (10:41 +0000)
committertanuma <tanuma@1ed66053-1c2d-0410-8867-f7571e6e31d3>
Thu, 17 Jun 2010 10:41:22 +0000 (10:41 +0000)
git-svn-id: http://10.144.169.20/repos/um/branches/l7vsd-3.x-ramiel-epoll-cond@10116 1ed66053-1c2d-0410-8867-f7571e6e31d3

l7directord/l7directord
l7vsd/include/tcp_socket_option.h
l7vsd/include/virtualservice_element.h
l7vsd/src/l7vsadm.cpp
l7vsd/src/tcp_session.cpp
l7vsd/src/virtualservice_tcp.cpp

index 0c62038..3f4e5d9 100644 (file)
@@ -926,7 +926,7 @@ sub validate_config {
              || $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);
@@ -985,14 +985,15 @@ sub validate_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);
                 }
             }
@@ -4920,65 +4921,82 @@ When communication with Client is SSL, the file name for SSL setting is
 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
 
index 1f8a7c6..1c755b2 100644 (file)
@@ -28,6 +28,10 @@ namespace l7vs
 {
 //! 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)
index c8bcb25..01e51f4 100644 (file)
@@ -78,6 +78,7 @@ public:
         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;
@@ -92,6 +93,7 @@ public:
                 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),
@@ -116,6 +118,7 @@ public:
                     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),
@@ -154,6 +157,7 @@ public:
                 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;
@@ -191,6 +195,7 @@ public:
                     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 &&
@@ -233,6 +238,7 @@ public:
                     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 &&
@@ -322,6 +328,7 @@ public:
                                     "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: "
@@ -342,6 +349,7 @@ public:
                    % 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
@@ -379,6 +387,7 @@ private:
                 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;
index 83b99df..6f72e5e 100644 (file)
@@ -1076,11 +1076,15 @@ bool    l7vs::l7vsadm::parse_opt_vs_socket_func(int &pos, int argc, char *argv[]
                 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;
@@ -1091,7 +1095,27 @@ bool    l7vs::l7vsadm::parse_opt_vs_socket_func(int &pos, int argc, char *argv[]
         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;
@@ -1914,7 +1938,11 @@ bool    l7vs::l7vsadm::parse_help_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG c
                   "  --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"
index 8a17151..9ece4fc 100644 (file)
@@ -1792,6 +1792,34 @@ void tcp_session::up_thread_realserver_connect(const TCP_PROCESS_TYPE_TAG proces
         } 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)) {
                         {
@@ -2220,6 +2248,34 @@ void tcp_session::up_thread_sorryserver_connect(const TCP_PROCESS_TYPE_TAG proce
 
         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)) {
index c0e307b..69dad51 100644 (file)
@@ -1643,11 +1643,14 @@ void l7vs::virtualservice_tcp::set_socket_option()
         }
 
         // 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)
@@ -1662,6 +1665,13 @@ void l7vs::virtualservice_tcp::set_socket_option()
         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) {
@@ -1684,7 +1694,6 @@ void l7vs::virtualservice_tcp::set_socket_option()
         }
 
         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;
@@ -1694,11 +1703,13 @@ void l7vs::virtualservice_tcp::set_socket_option()
         //----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");