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]