ACK only after second message

Yves Langisch yves at langisch.ch
Wed Nov 3 19:28:49 EDT 2010


Hi,

I have a tough time making my generic netlink communication running.

That's what I try to do:

user space			kernel module

register op (+attrs)	->	...
...			<-	register op (registred flag set)
insert op (+attr)	->	...
...			<-	insert (inserted flag set)

I thought that this should be a pretty simple, sequential scenario but I 
have problems with ACK messages. It looks like an ACK msg is only sent 
from the kernel side after the second operation (insert). As far as I 
understand using nl_send_auto_complete sets the NLM_F_ACK flag 
automatically and I should get an ACK msg for both operations.

My client code looks as follows:

	/* Allocate a new netlink socket */
	sock = nl_handle_alloc();
	if (sock == NULL) {
		LOGE("couldn't allocate socket");
		goto out;
	}

	/* Connect to the generic netlink socket in the kernel */
	int er = genl_connect(sock);
	if (er < 0) {
		LOGE("error while connecting %i", er);
		goto out;
	}

	/* obtain the family id for the CONTROL_EXMPL family */
	family = genl_ctrl_resolve(sock, "DROPSTOP");
	if (family < 0) {
		LOGE("error obtaining family");
		goto out;
	}

	/* allocate a new message */
	msg = nlmsg_alloc();

	/* make the header */
	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST,
			DROPSTOP_C_REGISTER, DROPSTOP_VERSION);

	/* add the data */
	nla_put_u32(msg, DROPSTOP_A_VERSION, DROPSTOP_VERSION);

	LOGI("Sending DROPSTOP_C_REGISTER");

	/* send the message */
	sent = nl_send_auto_complete(sock, msg);
	if (sent < 0) {
		LOGE("error sending message");
		goto out;
	}
	nlmsg_free(msg);

	//apparently no ACK for the first message?!?
	int ack = nl_wait_for_ack(sock);
	LOGI("ACK %i", ack);

	nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, receive_REGISTERED,
			(int *) &registered);

	LOGI("Start listening for REGISTERED");
	// Wait for the answer and receive it
	if (nl_recvmsgs_default(sock) < 0) {
		LOGE("Error while receiving message");
	}

	//next message
	msg = nlmsg_alloc();

	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, NLM_F_REQUEST,
			DROPSTOP_C_INSERT, DROPSTOP_VERSION);
	nla_put_u8(msg, DROPSTOP_A_SYSCALL, DROPSTOP_SOCKET_CONNECT);
	nla_put_u8(msg, DROPSTOP_A_PROTOCOL, IPPROTO_TCP);

	LOGI("Sending DROPSTOP_C_INSERT");
	if (nl_send_auto_complete(sock, msg) < 0) {
		LOGE("error sending message");
		goto out;
	}
	nlmsg_free(msg);
	int ack2 = nl_wait_for_ack(sock);
	LOGI("ACK %i", ack2);

	if (nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, receive_INSERTED,
			(int *) &inserted) <0){
		LOGE("ERRRRRRRRRRRRRRR");
	}
	LOGI("Start listening for INSERTED");
	// Wait for the answer and receive it
	if (nl_recvmsgs_default(sock)<0){
		LOGE("Fehler beim Empfang");
	}

	return 0;

Running the code as is gives the following output:

-
Sending DROPSTOP_C_REGISTER
ACK 0
Start listening for REGISTERED
Sending DROPSTOP_C_INSERT
Entering receive_REGISTERED
registration failed
ACK 0
Start listening for INSERTED
-

The first nl_wait_for_ack seems to mix up the message order. Commenting 
out the first nl_wait_for_ack gives the expected result:

-
Sending DROPSTOP_C_REGISTER
Start listening for REGISTERED
Entering receive_REGISTERED
registration successful
Sending DROPSTOP_C_INSERT
ACK 0
Start listening for INSERTED
entering receive_INSERTED
-

I don't know if I use the API in a wrong manner. The kernel module logic 
for receiving and replying is more or less the same. At least the reply 
part.

Any help is greatly appreciated!

Yves

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5198 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20101104/85327b51/attachment.p7s>


More information about the libnl mailing list