Hi Peter,

On Tue, Sep 01, 2009 at 02:00:02PM -0400, Peter Cudhea wrote:
> I am new to networking-discuss.  I searched for an earlier discussion of  
> the following, but didn't find one.

You'll find most kernel socket discussion on the volo-dev mailing
list, however, I do not remember one that covers timed connect calls.

> Does anyone have a cookbook to follow for how to write a  
> socket-connect-with-timeout function, for kernel sockets, using the  
> ksock_cb_connected callback?  The enclosed routines seem to be working.   
> I just want to double check that I am not out on the bleeding edge.

There is currently not a cookbook available. I have some example code,
but it does not cover the scenario you are looking at. 

A few comments on the code:

* Use ksocket_ioctl(.., FIONBIO, ..) to toggle the non-blocking
  behavior of the socket.

* You specify that you want both connected/connectfailed, but you
  forgot to set ksock_cb_connectfailed. There is also currently a bug
  that will affect your code (CR 6802067), until that is fixed, use
  the 'disconnected' callback.

* In a loopback scenario, it is possible that thread doing the
  ksocket_connect() is the same thread that will make the callback.
  Consider using a semaphore instead of the mutex/cv.

>
> Peter Cudhea
>
> Mutex idm_so_timed_socket_mutex is initiatialized at _init time.
>
> static void
> idm_so_socket_set_nonblock(struct sonode *node)
> {
>       (void) VOP_SETFL(node->so_vnode, node->so_flag,
>           (node->so_state | FNONBLOCK), CRED(), NULL);
> }
>
> static void
> idm_so_socket_set_block(struct sonode *node)
> {
>       (void) VOP_SETFL(node->so_vnode, node->so_flag,
>           (node->so_state & (~FNONBLOCK)), CRED(), NULL);
> }
>
>
> /* ARGSUSED */
> void *
> idm_so_timed_socket_connect_cb(ksocket_t ks,
>    ksocket_callback_event_t ev, void *arg, uintptr_t info)
> {
>       kcondvar_t      *cv = (kcondvar_t *) arg;
>       ASSERT(cv != NULL);
>       ASSERT(ev == KSOCKET_EV_CONNECTED || ev == KSOCKET_EV_CONNECTFAILED);
>
>       mutex_enter(&idm_so_timed_socket_mutex);
>       cv_signal(cv);
>       mutex_exit(&idm_so_timed_socket_mutex);
>       return (NULL);
> }
>
> int
> idm_so_timed_socket_connect(ksocket_t ks,
>    struct sockaddr_storage *sa, int sa_sz, int login_max_usec)
> {
>       clock_t         conn_login_max, lbolt;
>       struct sonode   *node;
>       int             rc;
>       ksocket_callbacks_t     ks_cb;
>       kcondvar_t              ks_cv;
>
>       node = (struct sonode *)ks;
>       conn_login_max = ddi_get_lbolt() + drv_usectohz(login_max_usec);
>
>       /* Set to non-block socket mode, with callback on connect */
>       bzero(&ks_cb, sizeof (ks_cb));
>       ks_cb.ksock_cb_flags = KSOCKET_CB_CONNECTED | KSOCKET_CB_CONNECTFAILED;
>       ks_cb.ksock_cb_connected =
>           (ksocket_callback_t) idm_so_timed_socket_connect_cb;
>       cv_init(&ks_cv, NULL, CV_DEFAULT, NULL);
>       (void) ksocket_setcallbacks(ks, &ks_cb, (void *)&ks_cv, CRED());
>       idm_so_socket_set_nonblock(node);
>
>       mutex_enter(&idm_so_timed_socket_mutex);
>       for (;;) {
>               rc = ksocket_connect(ks, (struct sockaddr *)sa, sa_sz, CRED());
>               if (rc == 0 || rc == EISCONN) {
>                       /* socket success or already success */
>                       rc = 0;
>                       break;
>               }
>               if ((rc != EINPROGRESS) && (rc != EALREADY)) {
>                       break;
>               }
>
>               lbolt = ddi_get_lbolt();
>               if (lbolt > conn_login_max) {
>                       /*
>                        * Connection retry timeout,
>                        * failed connect to target.
>                        */
>                       rc = ETIMEDOUT;
>                       break;
>               }
>               /* TCP connect still in progress.  Sleep until callback. */
>               (void) cv_timedwait(&ks_cv, &idm_so_timed_socket_mutex,
>                   conn_login_max);
>       }
>       mutex_exit(&idm_so_timed_socket_mutex);
>
>       /* resume blocking mode */
>       ksocket_setcallbacks(ks, NULL, NULL, CRED());
>       idm_so_socket_set_block(node);
>       cv_destroy(&ks_cv);
>
>       return (rc);
> }
>
>
>
> _______________________________________________
> networking-discuss mailing list
> [email protected]

Anders
_______________________________________________
networking-discuss mailing list
[email protected]

Reply via email to