public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Connector - how to start?
@ 2006-04-15  1:09 Libor Vanek
  2006-04-15  2:26 ` Randy.Dunlap
  2006-04-15 21:48 ` Jon Masters
  0 siblings, 2 replies; 18+ messages in thread
From: Libor Vanek @ 2006-04-15  1:09 UTC (permalink / raw)
  To: linux-kernel

Hi,
I'd like to start writing some small module using connector to send
messages to/from user-space. Unfortunately I'm absolutely not familiar
with netlink/connector API usage and I couldn't find any usefull
documentation (yes, I read Documentation/connector/ and tried Google).

So here's things which are not clear to me:
- the Documentation/connector containts only kernel-space example -
don't anybody have also "user-space client example"?
- how do I ACK message sent to/from user-space?
- in case of multiple clients listening how do I send message just to
(random) one (simple load balancing) or to all of them? (broadcasting)
- is there some "easy" way how to send longer messages then
CONNECTOR_MAX_MSG_SIZE?

Thanks for even small hints,
Libor Vanek

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-15  1:09 Connector - how to start? Libor Vanek
@ 2006-04-15  2:26 ` Randy.Dunlap
  2006-04-15  3:07   ` Matt Helsley
  2006-04-15 21:48 ` Jon Masters
  1 sibling, 1 reply; 18+ messages in thread
From: Randy.Dunlap @ 2006-04-15  2:26 UTC (permalink / raw)
  To: Libor Vanek; +Cc: linux-kernel

On Sat, 15 Apr 2006 03:09:05 +0200 Libor Vanek wrote:

> Hi,
> I'd like to start writing some small module using connector to send
> messages to/from user-space. Unfortunately I'm absolutely not familiar
> with netlink/connector API usage and I couldn't find any usefull
> documentation (yes, I read Documentation/connector/ and tried Google).
> 
> So here's things which are not clear to me:
> - the Documentation/connector containts only kernel-space example -
> don't anybody have also "user-space client example"?
> - how do I ACK message sent to/from user-space?
> - in case of multiple clients listening how do I send message just to
> (random) one (simple load balancing) or to all of them? (broadcasting)
> - is there some "easy" way how to send longer messages then
> CONNECTOR_MAX_MSG_SIZE?

There was a connector userspace example posted to lkml on
2005-SEP-28:

Subject: [RFC] Process Events Connector (test program)
From:	Matthew Helsley <matthltc@us.ibm.com>


It seems like one of the Red Hat guys had some netlink documentation
and sample programs at people.redhat.com, but I can't find that
just now.

---
~Randy

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-15  2:26 ` Randy.Dunlap
@ 2006-04-15  3:07   ` Matt Helsley
  2006-04-15  9:18     ` Evgeniy Polyakov
  0 siblings, 1 reply; 18+ messages in thread
From: Matt Helsley @ 2006-04-15  3:07 UTC (permalink / raw)
  To: Randy.Dunlap; +Cc: Libor Vanek, LKML, Evgeniy Polyakov

On Fri, 2006-04-14 at 19:26 -0700, Randy.Dunlap wrote:
> On Sat, 15 Apr 2006 03:09:05 +0200 Libor Vanek wrote:
> 
> > Hi,
> > I'd like to start writing some small module using connector to send
> > messages to/from user-space. Unfortunately I'm absolutely not familiar
> > with netlink/connector API usage and I couldn't find any usefull
> > documentation (yes, I read Documentation/connector/ and tried Google).
> > 
> > So here's things which are not clear to me:
> > - the Documentation/connector containts only kernel-space example -
> > don't anybody have also "user-space client example"?
> > - how do I ACK message sent to/from user-space?
> > - in case of multiple clients listening how do I send message just to
> > (random) one (simple load balancing) or to all of them? (broadcasting)
> > - is there some "easy" way how to send longer messages then
> > CONNECTOR_MAX_MSG_SIZE?
> 
> There was a connector userspace example posted to lkml on
> 2005-SEP-28:
> 
> Subject: [RFC] Process Events Connector (test program)
> From:	Matthew Helsley <matthltc@us.ibm.com>
> 
> 
> It seems like one of the Red Hat guys had some netlink documentation
> and sample programs at people.redhat.com, but I can't find that
> just now.
> 
> ---
> ~Randy

Subject:[ANNOUNCE] Test Program for Filesystem Events Reporter
                              From: 
Yi Yang <yang.y.yi@gmail.com>

might demonstrate what you're looking for as well.

	I don't believe there is an existing way to send messages longer than
CONNECTOR_MAX_MSG_SIZE. Perhaps you could send multiple messages with
the same sequence number but a different "fragment number" in the
message.

	However, if you're sending messages much larger than
CONNECTOR_MAX_MSG_SIZE perhaps the medium of communication is not
appropriate. Have you considered relay files?

Cheers,
	-Matt Helsley


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-15  3:07   ` Matt Helsley
@ 2006-04-15  9:18     ` Evgeniy Polyakov
       [not found]       ` <369a7ef40604150350x8e7dea1sbf1f83cb800dd1c3@mail.gmail.com>
       [not found]       ` <369a7ef40604160426s301dcd52r4c9826698d3d2f79@mail.gmail.com>
  0 siblings, 2 replies; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-15  9:18 UTC (permalink / raw)
  To: Matt Helsley; +Cc: Randy.Dunlap, Libor Vanek, LKML

[-- Attachment #1: Type: text/plain, Size: 2579 bytes --]

On Fri, Apr 14, 2006 at 08:07:17PM -0700, Matt Helsley (matthltc@us.ibm.com) wrote:
> On Fri, 2006-04-14 at 19:26 -0700, Randy.Dunlap wrote:
> > On Sat, 15 Apr 2006 03:09:05 +0200 Libor Vanek wrote:
> > 
> > > Hi,
> > > I'd like to start writing some small module using connector to send
> > > messages to/from user-space. Unfortunately I'm absolutely not familiar
> > > with netlink/connector API usage and I couldn't find any usefull
> > > documentation (yes, I read Documentation/connector/ and tried Google).
> > > 
> > > So here's things which are not clear to me:
> > > - the Documentation/connector containts only kernel-space example -
> > > don't anybody have also "user-space client example"?
> > > - how do I ACK message sent to/from user-space?
> > > - in case of multiple clients listening how do I send message just to
> > > (random) one (simple load balancing) or to all of them? (broadcasting)
> > > - is there some "easy" way how to send longer messages then
> > > CONNECTOR_MAX_MSG_SIZE?
> > 
> > There was a connector userspace example posted to lkml on
> > 2005-SEP-28:
> > 
> > Subject: [RFC] Process Events Connector (test program)
> > From:	Matthew Helsley <matthltc@us.ibm.com>
> > 
> > 
> > It seems like one of the Red Hat guys had some netlink documentation
> > and sample programs at people.redhat.com, but I can't find that
> > just now.
> > 
> > ---
> > ~Randy
> 
> Subject:[ANNOUNCE] Test Program for Filesystem Events Reporter
>                               From: 
> Yi Yang <yang.y.yi@gmail.com>
> 
> might demonstrate what you're looking for as well.
> 
> 	I don't believe there is an existing way to send messages longer than
> CONNECTOR_MAX_MSG_SIZE. Perhaps you could send multiple messages with
> the same sequence number but a different "fragment number" in the
> message.
> 
> 	However, if you're sending messages much larger than
> CONNECTOR_MAX_MSG_SIZE perhaps the medium of communication is not
> appropriate. Have you considered relay files?

I've attached simple userspace program used with w1, which sends
and receives connector messages. It can be also used as example of
netlink usage from userspace point of view.
If you want to use rtnetlink extensions, iproute2 is the best source.

Why do you want to send big messages over netlink?
Netlink is fast but not faster than char device for example, or read
from mapped area, although it is much more convenient to use.

Well, I can increase CONNECTOR_MAX_MSG_SIZE to maximum allowed 64k, if
there is really strong justification.

> Cheers,
> 	-Matt Helsley

-- 
	Evgeniy Polyakov

[-- Attachment #2: w1d.c --]
[-- Type: text/plain, Size: 8073 bytes --]

/*
 * 	w1d.c
 *
 * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
 * 
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>

#include <asm/byteorder.h>
#include <asm/types.h>

#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#include "w1_netlink.h"

static int need_exit;
static int send_seq;

static int send_cmd(FILE *out, int s, struct w1_netlink_msg *msg)
{
	struct cn_msg *cmsg;
	struct w1_netlink_msg *m;
	struct nlmsghdr *nlh;
	int size, err;
	
	size = NLMSG_SPACE(sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg) + msg->len);

	nlh = malloc(size);
	if (!nlh)
		return -ENOMEM;
	
	memset(nlh, 0, size);
	
	nlh->nlmsg_seq = send_seq++;
	nlh->nlmsg_pid = getpid();
	nlh->nlmsg_type = NLMSG_DONE;
	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(struct nlmsghdr));
	nlh->nlmsg_flags = 0;

	cmsg = NLMSG_DATA(nlh);
	
	cmsg->id.idx = CN_W1_IDX;
	cmsg->id.val = CN_W1_VAL;
	cmsg->seq = nlh->nlmsg_seq;
	cmsg->ack = 0;
	cmsg->len = sizeof(struct w1_netlink_msg) + msg->len;

	m = (struct w1_netlink_msg *)(cmsg + 1);
	memcpy(m, msg, sizeof(struct w1_netlink_msg));
	memcpy(m+1, msg->data, msg->len);
	
	err = send(s, nlh, size, 0);
	if (err == -1) {
		fprintf(out, "Failed to send: %s [%d].\n", strerror(errno), errno);
		free(nlh);
		return err;
	}
	free(nlh);

	return err;
}

static int w1_test_create_cmd(struct w1_netlink_msg *m, __u16 maxlen)
{
	char *cmd_data;
	__u16 i, newlen;
	struct w1_netlink_cmd *cmd;

	cmd_data = (char *)m->data;
	
	for (i=0; i<3; ++i) {
		newlen = (i+1)*10;

		if (newlen + sizeof(struct w1_netlink_cmd) + m->len > maxlen)
			break;

		cmd = (struct w1_netlink_cmd *)cmd_data;

		cmd->cmd = i;
		cmd->len = newlen;

		cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
		m->len += cmd->len + sizeof(struct w1_netlink_cmd);
	}

	return m->len;
}

static int w1_test_cmd_master(FILE *out, int s, __u32 id)
{
	char buf[1024];
	struct w1_netlink_msg *m;
	
	memset(buf, 0, sizeof(buf));

	m = (struct w1_netlink_msg *)buf;
	
	m->type = W1_MASTER_CMD;
	m->len = 0;
	m->id.mst.id = id;

	w1_test_create_cmd(m, sizeof(buf) - sizeof(struct w1_netlink_msg));

	return send_cmd(out, s, m);
}

static int w1_test_cmd_slave(FILE *out, int s, struct w1_reg_num *id)
{
	char buf[1024];
	struct w1_netlink_msg *m;
	struct w1_netlink_cmd *cmd;
	char *cmd_data;
	int i;
	
	memset(buf, 0, sizeof(buf));

	m = (struct w1_netlink_msg *)buf;
	
	m->type = W1_SLAVE_CMD;
	m->len = 0;
	memcpy(m->id.id, id, sizeof(m->id.id));

	cmd_data = (char *)m->data;
	
	for (i=0; i<3; ++i) {
		cmd = (struct w1_netlink_cmd *)cmd_data;

		cmd->cmd = i;
		cmd->len = (i+1)*10;
		
		cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);

		m->len += cmd->len + sizeof(struct w1_netlink_cmd);
	}

	return send_cmd(out, s, m);
}

static void w1_dump_reply(FILE *out, char *prefix, struct w1_netlink_msg *hdr)
{
	struct w1_netlink_cmd *cmd;
	unsigned char *hdr_data = hdr->data;
	unsigned int hdr_len = hdr->len;
	time_t tm;
	int i;

	time(&tm);
	
	while (hdr_len) {
		cmd = (struct w1_netlink_cmd *)hdr_data;
	
		fprintf(out, "%.24s : %s ", ctime(&tm), prefix);

		if (cmd->len + sizeof(struct w1_netlink_cmd) > hdr_len) {
			fprintf(out, "Malformed message.\n");
			break;
		}

		switch (cmd->cmd) {
			case W1_CMD_READ:
				fprintf(out, "READ: ");
				for (i=0; i<cmd->len; ++i)
					fprintf(out, "%02x ", cmd->data[i]);
				fprintf(out, "\n");
				break;
			default:
				fprintf(out, "cmd=%02x, len=%u.\n", cmd->cmd, cmd->len);
				break;
		}

		hdr_data += cmd->len + sizeof(struct w1_netlink_cmd);
		hdr_len -= cmd->len + sizeof(struct w1_netlink_cmd);
	}
}

static void w1_parse_master_reply(FILE *out, struct w1_netlink_msg *hdr)
{
	char prefix[128];

	snprintf(prefix, sizeof(prefix), "master: id=%08x", hdr->id.mst.id);
	w1_dump_reply(out, prefix, hdr);
}

static void w1_parse_slave_reply(FILE *out, struct w1_netlink_msg *hdr)
{
	char prefix[128];
	struct w1_reg_num id;
				
	memcpy(&id, hdr->id.id, sizeof(id));

	snprintf(prefix, sizeof(prefix), "slave: id=%02x.%012llx.%02x",
		id.family, (unsigned long long)id.id, id.crc); 
	w1_dump_reply(out, prefix, hdr);
}

void w1_dump_message(FILE *out, int s, struct cn_msg *msg)
{
	time_t tm;
	struct w1_netlink_msg *data = (struct w1_netlink_msg *)(msg + 1);
	unsigned int i;
	
	while (msg->len) {
		struct w1_reg_num id;
		
		time(&tm);
#if 0
		fprintf(out, "%.24s : %08x.%08x, len=%u, seq=%u, ack=%u, data->len=%u.\n", 
				ctime(&tm), msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack, data->len);
#endif
		switch (data->type) {
			case W1_MASTER_ADD:
			case W1_MASTER_REMOVE:
				if (data->type == W1_MASTER_ADD)
					w1_test_cmd_master(out, s, data->id.mst.id);
				
				fprintf(out, "%.24s : master has been %.8s: id=%08x.\n", 
					ctime(&tm), 
					(data->type == W1_MASTER_ADD)?"added":"removed",
					data->id.mst.id);
				break;
			
			case W1_SLAVE_ADD:
			case W1_SLAVE_REMOVE:
				memcpy(&id, data->id.id, sizeof(id));

				if (data->type == W1_SLAVE_ADD)
					w1_test_cmd_slave(out, s, &id);
				
				fprintf(out, "%.24s :  slave has been %.8s: id=%02x.%012llx.%02x\n", 
					ctime(&tm), 
					(data->type == W1_SLAVE_ADD)?"added":"removed",
					id.family, (unsigned long long)id.id, id.crc); 
				break;
			case W1_MASTER_CMD:
				w1_parse_master_reply(out, data);
				break;
			case W1_SLAVE_CMD:
				w1_parse_slave_reply(out, data);
				break;
			default:
				fprintf(out, "%.24s : type=%02x", ctime(&tm), data->type);
				
				for (i=0; i<sizeof(data->id.id); ++i)
					fprintf(out, "%02x.", data->id.id[i]);
				fprintf(out, "\n");
		}
		fflush(out);

		msg->len -= sizeof(struct w1_netlink_msg) + data->len;
		data = (struct w1_netlink_msg *)(((char *)data) + sizeof(struct w1_netlink_msg) + data->len);
	}
}

int main(int argc, char *argv[])
{
	int s;
	unsigned char buf[1024];
	int len;
	struct sockaddr_nl l_local;
	struct cn_msg *msg;
	FILE *out;
	struct pollfd pfd;
	struct nlmsghdr *reply;
	
	if (argc < 2)
		out = stdout;
	else {
		out = fopen(argv[1], "a+");
		if (!out) {
			fprintf(stderr, "Unable to open %s for writing: %s\n", 
					argv[1], strerror(errno));
			out = stdout;
		}
	}
	
	memset(buf, 0, sizeof(buf));
	
	s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
	if (s == -1) {
		perror("socket");
		return -1;
	}
	
	l_local.nl_family = AF_NETLINK;
	l_local.nl_groups = 23;
	l_local.nl_pid    = getpid();
	
	if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
		perror("bind");
		close(s);
		return -1;
	}

	pfd.fd = s;

	while (!need_exit)
	{
		pfd.events = POLLIN;
		pfd.revents = 0;
		switch (poll(&pfd, 1, -1)) {
			case 0:
				need_exit = 1;
				break;
			case -1:
				if (errno != EINTR) {
					need_exit = 1;
					break;
				}
				continue;
			default:
				break;
		}
		if (need_exit)
			break;

		len = recv(s, buf, sizeof(buf), 0);
		if (len == -1) {
			perror("recv buf");
			close(s);
			return -1;
		}

		reply = (struct nlmsghdr *)buf;

		switch (reply->nlmsg_type) {
			case NLMSG_ERROR:
				fprintf(out, "Error message received.\n");
				fflush(out);
				break;
			case NLMSG_DONE:
				msg = (struct cn_msg *)NLMSG_DATA(reply);
				w1_dump_message(out, s, msg);
				break;
			default:
				break;
		}

	}
	
	close(s);
	return 0;
}


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]       ` <369a7ef40604150350x8e7dea1sbf1f83cb800dd1c3@mail.gmail.com>
@ 2006-04-15 11:14         ` Evgeniy Polyakov
  2006-04-15 12:18           ` Paul Collins
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-15 11:14 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Sat, Apr 15, 2006 at 12:50:46PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> Hi

Hello.

> > Why do you want to send big messages over netlink?
> > Netlink is fast but not faster than char device for example, or read
> > from mapped area, although it is much more convenient to use.
> >
> > Well, I can increase CONNECTOR_MAX_MSG_SIZE to maximum allowed 64k, if
> > there is really strong justification.
> 
> I need to send messages containing several (1 to 3) file names. And
> "MAXPATHLEN" is 1024b (usually it's much less but I can't rely on
> that).

$ touch `perl -e 'print "A"x1024'`
touch: cannot touch
`AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA':
File name too long

Only 255 is allowed in my system.

> I got working solution using procfs but my (diploma thesis) project
> manager want's me to use netlink/connector solution...

Well, it is strong justification, since connector does not use
CONNECTOR_MAX_MSG_SIZE except for checking that message size is less
that this value, but as pointed above, filename can not be that long,
although it can exceed above value when concatenated with directory
names. But in this case it can exceed any other limits, and it can be
impossible to allocate such a big buffer to store the whole path.

So you will need to create some kind of tree strucuture to store your 
names there, since it is wrong thing to allocate a buffer to store the
whole path as is. But in this case you do not need to
increase CONNECTOR_MAX_MSG_SIZE.

> Thanks for help,
> Libor Vanek

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-15 11:14         ` Evgeniy Polyakov
@ 2006-04-15 12:18           ` Paul Collins
  2006-04-15 12:38             ` Evgeniy Polyakov
  0 siblings, 1 reply; 18+ messages in thread
From: Paul Collins @ 2006-04-15 12:18 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: Libor Vanek, Matt Helsley, Randy.Dunlap, LKML

Evgeniy Polyakov <johnpol@2ka.mipt.ru> writes:

> On Sat, Apr 15, 2006 at 12:50:46PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
>> Hi
>
> Hello.
>
>> > Why do you want to send big messages over netlink?
>> > Netlink is fast but not faster than char device for example, or read
>> > from mapped area, although it is much more convenient to use.
>> >
>> > Well, I can increase CONNECTOR_MAX_MSG_SIZE to maximum allowed 64k, if
>> > there is really strong justification.
>> 
>> I need to send messages containing several (1 to 3) file names. And
>> "MAXPATHLEN" is 1024b (usually it's much less but I can't rely on
>> that).
>
> $ touch `perl -e 'print "A"x1024'`
> touch: cannot touch
> `AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA':
> File name too long
>
> Only 255 is allowed in my system.

There are two limits though, the component length limit (NAME_MAX),
and the overall length limit (PATH_MAX).  For example:

$ mkdir -p `perl -e 'print "A"x255'`/`perl -e 'print "B"x255'`/`perl -e 'print "C"x255'`/`perl -e 'print "D"x255'`

works fine here.

However, with 256 I get "File name too long", as you did.

-- 
Dag vijandelijk luchtschip de huismeester is dood

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-15 12:18           ` Paul Collins
@ 2006-04-15 12:38             ` Evgeniy Polyakov
       [not found]               ` <369a7ef40604150624n28da8895if158a2c13cac2b9e@mail.gmail.com>
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-15 12:38 UTC (permalink / raw)
  To: Libor Vanek, Matt Helsley, Randy.Dunlap, LKML

On Sat, Apr 15, 2006 at 10:18:31PM +1000, Paul Collins (paul@briny.ondioline.org) wrote:
> Evgeniy Polyakov <johnpol@2ka.mipt.ru> writes:
> 
> > On Sat, Apr 15, 2006 at 12:50:46PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> >> Hi
> >
> > Hello.
> >
> >> > Why do you want to send big messages over netlink?
> >> > Netlink is fast but not faster than char device for example, or read
> >> > from mapped area, although it is much more convenient to use.
> >> >
> >> > Well, I can increase CONNECTOR_MAX_MSG_SIZE to maximum allowed 64k, if
> >> > there is really strong justification.
> >> 
> >> I need to send messages containing several (1 to 3) file names. And
> >> "MAXPATHLEN" is 1024b (usually it's much less but I can't rely on
> >> that).
> >
> > $ touch `perl -e 'print "A"x1024'`
> > touch: cannot touch
> > `AA...AA':
> > File name too long
> >
> > Only 255 is allowed in my system.
> 
> There are two limits though, the component length limit (NAME_MAX),
> and the overall length limit (PATH_MAX).  For example:
> 
> $ mkdir -p `perl -e 'print "A"x255'`/`perl -e 'print "B"x255'`/`perl -e 'print "C"x255'`/`perl -e 'print "D"x255'`
> 
> works fine here.
> 
> However, with 256 I get "File name too long", as you did.

Sure, as pointed in previous e-mail, several concatenated directories can exceed any resonable limit,
even PATH_MAX (4k):
$ pwd | wc
      1       1    4113

So it is wrong idea to transfer the whole name in one message, which
will not only add huge overhead (for each subdir one must transfer the
whole path for the parent dir), but can be impossible to allocate such a
buffer in kernelspace to store the whole pathname.

> -- 
> Dag vijandelijk luchtschip de huismeester is dood

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-15  1:09 Connector - how to start? Libor Vanek
  2006-04-15  2:26 ` Randy.Dunlap
@ 2006-04-15 21:48 ` Jon Masters
  1 sibling, 0 replies; 18+ messages in thread
From: Jon Masters @ 2006-04-15 21:48 UTC (permalink / raw)
  To: Libor Vanek; +Cc: linux-kernel

On 4/15/06, Libor Vanek <libor.vanek@gmail.com> wrote:

> I'd like to start writing some small module using connector to send
> messages to/from user-space. Unfortunately I'm absolutely not familiar
> with netlink/connector API usage and I couldn't find any usefull
> documentation (yes, I read Documentation/connector/ and tried Google).

So, time to ask the question.

I've been thinking for the past couple of weeks of hacking at the
different users of netlink and trying to get everyone to play nicely
together - if we're pushing things like connector, why can't we make
this a general solution? (read: why do uevents have to be seperate?
why are we forced to a particular protocol number with connector?
etc.?).

Jon.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]               ` <369a7ef40604150624n28da8895if158a2c13cac2b9e@mail.gmail.com>
@ 2006-04-16  7:53                 ` Evgeniy Polyakov
  2006-04-16 17:09                   ` Evgeniy Polyakov
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-16  7:53 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Sat, Apr 15, 2006 at 03:24:26PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> > > However, with 256 I get "File name too long", as you did.
> >
> > Sure, as pointed in previous e-mail, several concatenated directories can exceed any resonable limit,
> > even PATH_MAX (4k):
> > $ pwd | wc
> >       1       1    4113
> >
> > So it is wrong idea to transfer the whole name in one message, which
> > will not only add huge overhead (for each subdir one must transfer the
> > whole path for the parent dir), but can be impossible to allocate such a
> > buffer in kernelspace to store the whole pathname.
> 
> OK, so what would you suggest as the right "tool" to transfer these
> (full path text) information?
> 
> I see these options:
> 1, Keep using procfs (I don't like it)
> 2, Use connector and create such "communication protocol" that it'll
> be able to transfer such long messages in more datagrams (even if
> 99.99% of messages will fit 1 datagram)
> 3, Some other API to transfer information to user-space and back?
> 
> I'll probably go with 2, but I'd be more then happy to hear any
> comments about this...


In general case using any tool you will be unable to transfer the whole
path in one shot, consider low memory condition and you try to allocate
a page with high order.
So it is required to split your path into multiple blocks, I would
recommend to use messages with names between slashes, i.e.
/home/test/aaa/bbb/ccc will be sent as 5 messages with /home, test, aaa,
bbb and ccc data, this will also reduce overhead when there are several
files or directories in one parent dir. Each message should also include
some reference to which parent dir it belongs. This will also speed
things up noticebly, since you will not rescan the whole path when new
file is created, only parent dir.

I wish you success in this hacking journey.

> Libor Vanek

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]       ` <369a7ef40604160426s301dcd52r4c9826698d3d2f79@mail.gmail.com>
@ 2006-04-16 11:40         ` Evgeniy Polyakov
       [not found]           ` <369a7ef40604160509xcf2caadi782b90da956639d5@mail.gmail.com>
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-16 11:40 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Sun, Apr 16, 2006 at 01:26:10PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> Hi,
> 
> > I've attached simple userspace program used with w1, which sends
> > and receives connector messages. It can be also used as example of
> > netlink usage from userspace point of view.
> 
> Maybe I'm really stupid and/or blind but I can't find in this example
> (from my point of view) quite important features:
> 
> - there is no way how can user-space part say what "cb_id.idx" and
> "cb_id.val" it should accept (as far as I understand these are used
> for settings "message type" - what SW is using these)

"idx" field is a group number userspace binds to, "val" is a private
identificator which is used as you like.

> - I can't find neither in cn_test.c nor w1_netlink.c (which is the
> only part I found connector used in) any way of detecting if message
> was delivered to/from user-space

If cn_netlink_send() returns zero this means message was queued into
userspace socket. In case of error negative value is returned.

> - the very same is for detecting if there is some user-space
> "reciever" (there is some mention about this in
> Documentantation/connector/connector.txt but it's not working to
> myself - I got 2.6.17-pre1-mm2)

connector uses netlink_has_listeners(), but it can produce false
positives, in this case netlink_broadcast() will say the final word.
If message has been added into socket's queue netlink_broadcast(), which
is used in connector, returns zero, and it's return value is propagated
back to original caller of cn_netlink_send().

Message from userspace is always delivered, and in this case appropriate
callback is called.

> Maybe connector doesn't support these things... ?
> 
> Libor Vanek

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]           ` <369a7ef40604160509xcf2caadi782b90da956639d5@mail.gmail.com>
@ 2006-04-16 13:25             ` Evgeniy Polyakov
       [not found]               ` <369a7ef40604160632t16f6aab9u687a6b359997d7ea@mail.gmail.com>
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-16 13:25 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Sun, Apr 16, 2006 at 02:09:57PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> On 4/16/06, Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:
> > On Sun, Apr 16, 2006 at 01:26:10PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> > > Hi,
> > >
> > > > I've attached simple userspace program used with w1, which sends
> > > > and receives connector messages. It can be also used as example of
> > > > netlink usage from userspace point of view.
> > >
> > > Maybe I'm really stupid and/or blind but I can't find in this example
> > > (from my point of view) quite important features:
> > >
> > > - there is no way how can user-space part say what "cb_id.idx" and
> > > "cb_id.val" it should accept (as far as I understand these are used
> > > for settings "message type" - what SW is using these)
> >
> > "idx" field is a group number userspace binds to, "val" is a private
> > identificator which is used as you like.
> 
> See attached example please - I've created simple kernel module
> "cn_test" which on recieving message from cn_user_send should "bounce
> it" to cn_user_recv.
> 
> If I change "l_local.nl_groups" in cn_user_send.c/cn_user/rect.c to
> anything else (e.g. "l_local.nl_groups = 0x5;" it still works... (all
> messages are delivered...)

It looks like you are using old kernel, which had ability to multicast
messages not only to specified group but to any other which has at least
one bit from original group set, since 23 & 0x5 is true, message will be
delivered.
But in more recent kernel this is not the case anymore.

I will test your module tomorrow and report if it works correctly or
not. I've just tested w1 connector with completely different group
number which does have the same bits set (group 3 in kernel and group 4
in bind time in userspace), and message was delivered successfully.
I will investigate it further tomorrow.

> > > - I can't find neither in cn_test.c nor w1_netlink.c (which is the
> > > only part I found connector used in) any way of detecting if message
> > > was delivered to/from user-space
> > If cn_netlink_send() returns zero this means message was queued into
> > userspace socket. In case of error negative value is returned.
> > > - the very same is for detecting if there is some user-space
> > > "reciever" (there is some mention about this in
> > > Documentantation/connector/connector.txt but it's not working to
> > > myself - I got 2.6.17-pre1-mm2)
> >
> > connector uses netlink_has_listeners(), but it can produce false
> > positives, in this case netlink_broadcast() will say the final word.
> > If message has been added into socket's queue netlink_broadcast(), which
> > is used in connector, returns zero, and it's return value is propagated
> > back to original caller of cn_netlink_send().
> 
> Yes, but "cn_netlink_send()" return zero even in case than there is no
> reciever (so message is lost because there is nobody to listen to it)
> - see attached cn_test.c:30

No, cn_netlink_send() only returns zero if there are listeners and
message was successfully delivered.

> > Message from userspace is always delivered, and in this case appropriate
> > callback is called.
> 
> Libor Vanek

> /*
>  * 	cn_test.c
>  */
> 
> #include <linux/kernel.h>
> #include <linux/module.h>
> #include <linux/moduleparam.h>
> #include <linux/skbuff.h>
> #include <linux/timer.h>
> 
> #include <linux/connector.h>
> 
> static struct cb_id cn_test_id = { 0x3, 0x1 };
> static char cn_test_name[] = "cn_test";
> static struct sock *nls;

You do not need any socket when you use connector.

> static int seq_id = 0;
> 
> void cn_test_callback(void *data)
> {
> 	int ret;
> 	struct cn_msg *msg = (struct cn_msg *)data;
> 	
> 	printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s\n",
> 	       __func__, jiffies, msg->id.idx, msg->id.val,
> 	       msg->seq, msg->ack, msg->len, (char *)msg->data);
> 
> 	msg->seq = seq_id++;
> 	msg->ack = 0;
> 
> 	ret = cn_netlink_send(msg, 0x3, gfp_any());

This will deliver message to group 3 but not that one specified in
cn_msg header. You need to set second parameter to zero if you want to
automatically select the right group.

> 	printk("Resend, retval: %i\n", ret);
> }
> 
> static int cn_test_init(void)
> {
> 	int err;
> 
> 	err = cn_add_callback(&cn_test_id, cn_test_name, cn_test_callback);
> 	if (err)
> 		goto err_out;
> 
> 	printk(KERN_INFO "cn_test loaded\n");
> 	return 0;
> 
> err_out:
> 	if (nls && nls->sk_socket)
> 		sock_release(nls->sk_socket);

No need to release never initialized socket, although it is set to zero
and sock_release() is never called.

> 	return err;
> }
> 
> static void cn_test_fini(void)
> {
> 	cn_del_callback(&cn_test_id);
> 	if (nls && nls->sk_socket)
> 		sock_release(nls->sk_socket);
> 	printk(KERN_INFO "cn_test unloaded\n");
> }
> 
> module_init(cn_test_init);
> module_exit(cn_test_fini);
> 
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Libor Vanek <libor.vanek@gmail.com>");
> MODULE_DESCRIPTION("Connector's test module");
> 

...

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]               ` <369a7ef40604160632t16f6aab9u687a6b359997d7ea@mail.gmail.com>
@ 2006-04-16 14:19                 ` Evgeniy Polyakov
  2006-04-18  6:07                 ` Evgeniy Polyakov
  1 sibling, 0 replies; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-16 14:19 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Sun, Apr 16, 2006 at 03:32:02PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:

> It's really strange... Maybe when I'm trying to send from kernel
> module to user space and kernel moduele is registred with same group
> ID, then it's taken as listener (even when it's not delivered in the
> end...). Maybe I should have one group ID for user => kernel and
> different ID for kernel => user messages?

Message should be received only when it is sent to the same group as
specified at bind(subscribe actually) time, 
I need to investigate this strange issue more
deeply. Current symptom is that netlink messages are delivered  to any
group which process is bound to no matter which one is specified in
netlink header (tested with userspace socket subscribed to group 17, and
kernel sets group number to 1,3,4,5,17 if group number is set to 2 or more
than 5 message is not delivered as expected).

Btw, you need to not only bind to specified group but also to subscribe
to it. This step is described in Documentation/connector/ and requires
one setsockopt call.

> Libor Vanek

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-16  7:53                 ` Evgeniy Polyakov
@ 2006-04-16 17:09                   ` Evgeniy Polyakov
  0 siblings, 0 replies; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-16 17:09 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Sun, Apr 16, 2006 at 11:53:23AM +0400, Evgeniy Polyakov (johnpol@2ka.mipt.ru) wrote:
> On Sat, Apr 15, 2006 at 03:24:26PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> > OK, so what would you suggest as the right "tool" to transfer these
> > (full path text) information?
> > 
> > I see these options:
> > 1, Keep using procfs (I don't like it)
> > 2, Use connector and create such "communication protocol" that it'll
> > be able to transfer such long messages in more datagrams (even if
> > 99.99% of messages will fit 1 datagram)
> > 3, Some other API to transfer information to user-space and back?
> > 
> > I'll probably go with 2, but I'd be more then happy to hear any
> > comments about this...

Btw, I forgot to say, that CONNECTOR_MAX_MSG_SIZE restriction to maximum
allowed message size is only applicable for userspace->kernelspace
direction. Messages, emmited by kernel, can have any size you want.

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]               ` <369a7ef40604160632t16f6aab9u687a6b359997d7ea@mail.gmail.com>
  2006-04-16 14:19                 ` Evgeniy Polyakov
@ 2006-04-18  6:07                 ` Evgeniy Polyakov
       [not found]                   ` <369a7ef40604190439v6e8f1bf6lf52cfab5af3a93af@mail.gmail.com>
  1 sibling, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-18  6:07 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

bind() nladdr value is a bitmask of groups, not a single group number,
it was done for backward compatibility, so bind(5) is equal to
subscribe(1) and subscribe(3). That is why you saw messages without
subscription.

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
       [not found]                   ` <369a7ef40604190439v6e8f1bf6lf52cfab5af3a93af@mail.gmail.com>
@ 2006-04-19 12:14                     ` Evgeniy Polyakov
  2006-04-20 15:12                       ` Libor Vanek
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-19 12:14 UTC (permalink / raw)
  To: Libor Vanek; +Cc: Matt Helsley, Randy.Dunlap, LKML

On Wed, Apr 19, 2006 at 01:39:08PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
> Ok, thanks. And is there some way how to sign to simply some group
> number? (not through this bit mask but directly through group number -
> yes, I know I can "convert" the number)

bind() to zero and then subscribe can work.

> And what about my other issue I had in my simple example
> module/userspace SW - that cn_netlink_send returned 0 even when there
> was no listener - have you found something wrong in connector or (more
> probable) in my example?

With the latest 2.6 git tree I get following:

w1_netlink_send: cn_netlink_send() returned -3.

when there are no users.

Can you check if there is 
return netlink_broadcast(); string in the cn_netlink_send() in your
tree?

> Thanks,
> Libor Vanek
> 
> On 4/18/06, Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:
> > bind() nladdr value is a bitmask of groups, not a single group number,
> > it was done for backward compatibility, so bind(5) is equal to
> > subscribe(1) and subscribe(3). That is why you saw messages without
> > subscription.
> >
> > --
> >         Evgeniy Polyakov
> >

-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-19 12:14                     ` Evgeniy Polyakov
@ 2006-04-20 15:12                       ` Libor Vanek
  2006-04-20 15:25                         ` Evgeniy Polyakov
  0 siblings, 1 reply; 18+ messages in thread
From: Libor Vanek @ 2006-04-20 15:12 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: LKML

[-- Attachment #1: Type: text/plain, Size: 582 bytes --]

Hi,
I got it all finally everything working with "setsockopt" as suggested.

In case anybody else wants to experiment with connector, I attach my
examples (maybe add it to Documentation/connector/?)

Anyway - there are two more issues (not bugs) which I'd like to solve:
- When sending message from kernel, cn_netlink_send returns an error
in case when there is no reciever - BUT user space "send" doesn't
return an error when there is no reciever in kernel :-(

- How (if) can I do ACK (acknoledge received and processed message)?

Thanks for your help,
Libor Vanek

[-- Attachment #2: cn_recv.c --]
[-- Type: text/x-csrc, Size: 1035 bytes --]

/*
 * 	cn_recv.c
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/timer.h>

#include <linux/connector.h>

static struct cb_id cn_recv_id = { 0x3, 0x1 };
static char cn_recv_name[] = "cn_recv";

void cn_recv_callback(void *data)
{
	struct cn_msg *msg = (struct cn_msg *)data;
	
	printk("%s: %lu: idx=%x, val=%x, seq=%u, ack=%u, len=%d: %s\n",
	       __func__, jiffies, msg->id.idx, msg->id.val,
	       msg->seq, msg->ack, msg->len, (char *)msg->data);
}

static int cn_recv_init(void)
{
	int err;

	err = cn_add_callback(&cn_recv_id, cn_recv_name, cn_recv_callback);

	printk(KERN_INFO "cn_recv loaded, cn_add_callback retval: %i\n", err);
	return 0;
}

static void cn_recv_fini(void)
{
	cn_del_callback(&cn_recv_id);
	printk(KERN_INFO "cn_recv unloaded\n");
}

module_init(cn_recv_init);
module_exit(cn_recv_fini);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Libor Vanek <libor.vanek@gmail.com>");
MODULE_DESCRIPTION("Connector's test recieve module");





[-- Attachment #3: cn_send.c --]
[-- Type: text/x-csrc, Size: 1104 bytes --]

/*
 * 	cn_send.c
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/skbuff.h>
#include <linux/timer.h>

#include <linux/connector.h>

static struct cb_id cn_send_id = { 0x3, 0x1 };
static int seq_id = 0;

void my_send_test(void)
{
	struct cn_msg *msg;
	char data[32];
	int ret;
	
	msg = kmalloc(sizeof(*msg) + sizeof(data), GFP_ATOMIC);
	memset(msg, 0, sizeof(*msg) + sizeof(data));

	msg->id.idx = cn_send_id.idx;
	msg->id.val = cn_send_id.val;
	msg->ack = 0;
	msg->seq = seq_id++;
	msg->len = 5;

	msg->len = sizeof(data);
	msg->len = scnprintf(data, sizeof(data), "Ping") + 1;
	memcpy(msg + 1, data, msg->len);

	ret = cn_netlink_send(msg, cn_send_id.idx, gfp_any());
	kfree(msg);
	printk("Sent, retval: %i\n", ret);
}

static int cn_send_init(void)
{
	my_send_test();
	return 0;
}

static void cn_send_fini(void)
{
	printk(KERN_INFO "cn_send unloaded\n");
}

module_init(cn_send_init);
module_exit(cn_send_fini);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Libor Vanek <libor.vanek@gmail.com>");
MODULE_DESCRIPTION("Connector's test send module");





[-- Attachment #4: cn_user_recv.c --]
[-- Type: text/x-csrc, Size: 2014 bytes --]

/*
 * 	cn_user_recv.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>

#include <endian.h>
#include <asm/types.h>

#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <linux/connector.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

void process_msg(int s, struct cn_msg *msg)
{
	fprintf(stdout, "Message: %08x.%08x, len=%u, seq=%u, ack=%u, len=%u %s\n",
		msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack, msg->len, (void *)msg->data);
}

int main(int argc, char *argv[])
{
	int s;
	unsigned char buf[1024];
	int len, need_exit;

	struct sockaddr_nl l_local;
	struct cn_msg *msg;
	struct pollfd pfd;
	struct nlmsghdr *reply;
	
	memset(buf, 0, sizeof(buf));
	
	s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
	if (s == -1) {
		perror("socket");
		return -1;
	}
	
	l_local.nl_family = AF_NETLINK;
	l_local.nl_groups = 0x3;
	l_local.nl_pid    = getpid();
	
	if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
		perror("bind");
		close(s);
		return -1;
	}
	int on = l_local.nl_groups;
	if (setsockopt(s, 270, 1, &on, sizeof(on))) {
		perror("setsockopt");
		close(s);
		return -1;
	}

	pfd.fd = s;

	need_exit = 0;
	while (!need_exit) {
		pfd.events = POLLIN;
		pfd.revents = 0;
		switch (poll(&pfd, 1, -1)) {
			case 0:
				need_exit = 1;
				break;
			case -1:
				if (errno != EINTR) {
					need_exit = 1;
					break;
				}
				continue;
			default:
				break;
		}
		if (need_exit)
			break;

		len = recv(s, buf, sizeof(buf), 0);
		if (len == -1) {
			perror("recv buf");
			close(s);
			return -1;
		}

		reply = (struct nlmsghdr *)buf;

		switch (reply->nlmsg_type) {
			case NLMSG_ERROR:
				fprintf(stdout, "Error message received.\n");
				fflush(stdout);
				break;
			case NLMSG_DONE:
				msg = (struct cn_msg *)NLMSG_DATA(reply);
				process_msg(s, msg);
				break;
			default:
				break;
		}
		
	}
	
	close(s);
	return 0;
}






[-- Attachment #5: cn_user_send.c --]
[-- Type: text/x-csrc, Size: 1942 bytes --]

/*
 * 	cn_user_send.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>

#include <endian.h>
#include <asm/types.h>

#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <linux/connector.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>

#define GROUP	0x3

static int send_seq;

static int send_cmd(int s)
{
	static char txtmsg[] = "Ping pong";
	void *m;
	struct cn_msg *cmsg;
	struct nlmsghdr *nlh;
	int size, err;
	
	size = NLMSG_SPACE(sizeof(struct cn_msg) + sizeof(txtmsg));

	nlh = malloc(size);
	if (!nlh)
		return -ENOMEM;
	
	memset(nlh, 0, size);
	
	nlh->nlmsg_seq = send_seq++;
	nlh->nlmsg_pid = getpid();
	nlh->nlmsg_type = NLMSG_DONE;
	nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(struct nlmsghdr));
	nlh->nlmsg_flags = 0;

	cmsg = NLMSG_DATA(nlh);
	
	cmsg->id.idx = GROUP;
	cmsg->id.val = 0x1;
	cmsg->seq = nlh->nlmsg_seq;
	cmsg->ack = 0;
	cmsg->len = sizeof(txtmsg);

	m = (void *)(cmsg + 1);
	memcpy(m, (void *)txtmsg, sizeof(txtmsg));
	
	err = send(s, nlh, size, 0);
	if (err == -1) {
		fprintf(stdout, "Failed to send: %s [%d].\n", strerror(errno), errno);
	}
	free(nlh);

	return err;
}

int main(int argc, char *argv[])
{
	int s;
	unsigned char buf[1024];
	int len;

	send_seq = 0;

	struct sockaddr_nl l_local;
	struct cn_msg *msg;
	struct nlmsghdr *reply;
	
	memset(buf, 0, sizeof(buf));
	
	s = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
	if (s == -1) {
		perror("socket");
		return -1;
	}
	
	l_local.nl_family = AF_NETLINK;
	l_local.nl_groups = GROUP;
	l_local.nl_pid    = getpid();
	
	if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
		perror("bind");
		close(s);
		return -1;
	}
	int on = l_local.nl_groups;
	if (setsockopt(s, 270, 1, &on, sizeof(on))) {
		perror("setseckopt");
		close(s);
		return -1;
	}

	send_cmd(s);
	
	close(s);
	return 0;
}






^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-20 15:12                       ` Libor Vanek
@ 2006-04-20 15:25                         ` Evgeniy Polyakov
  2006-04-20 15:32                           ` Libor Vanek
  0 siblings, 1 reply; 18+ messages in thread
From: Evgeniy Polyakov @ 2006-04-20 15:25 UTC (permalink / raw)
  To: Libor Vanek; +Cc: LKML

On Thu, Apr 20, 2006 at 05:12:33PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:

> - When sending message from kernel, cn_netlink_send returns an error
> in case when there is no reciever - BUT user space "send" doesn't
> return an error when there is no reciever in kernel :-(

Userspace sends it into kernel socket. Groups were created for
userspace's sockets, so there is always a listener in kernelspace.

> - How (if) can I do ACK (acknoledge received and processed message)?

I put seq and ack fields into connector header, and described a simple
protocol for it's usage, but it does require some work by driver author, 
it is impossible to generate automatic ack messages in netlink 
(well, it is possible to generate nlmsgerr message sending but generally 
it is not what people want with protocols designed over connector).

> Thanks for your help,
> Libor Vanek

> /*
>  * 	cn_send.c
>  */

...

> void my_send_test(void)
> {
> 	struct cn_msg *msg;
> 	char data[32];
> 	int ret;
> 	
> 	msg = kmalloc(sizeof(*msg) + sizeof(data), GFP_ATOMIC);

Not a good style of allocating data from atomic pool without checks for
return value.
Btw, you do not need to allocate it dynamically, 
char msg[sizeof(struct cn_msg) + 32] will work too.

...

> /*
>  * 	cn_user_recv.c
>  */

...
 
> 	l_local.nl_family = AF_NETLINK;
> 	l_local.nl_groups = 0x3;
> 	l_local.nl_pid    = getpid();
> 	
> 	if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) {
> 		perror("bind");
> 		close(s);
> 		return -1;
> 	}
> 	int on = l_local.nl_groups;
> 	if (setsockopt(s, 270, 1, &on, sizeof(on))) {
> 		perror("setsockopt");
> 		close(s);
> 		return -1;
> 	}

In this example you will receive messages for groups 1, 2 (bind time
gropus 0x3 is equal to (1<<(1-1)) | (1<<(2-1))) and group 3 (you
have subscribed to that gropu explicitly).


-- 
	Evgeniy Polyakov

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: Connector - how to start?
  2006-04-20 15:25                         ` Evgeniy Polyakov
@ 2006-04-20 15:32                           ` Libor Vanek
  0 siblings, 0 replies; 18+ messages in thread
From: Libor Vanek @ 2006-04-20 15:32 UTC (permalink / raw)
  To: Evgeniy Polyakov; +Cc: LKML

Hi,

On 4/20/06, Evgeniy Polyakov <johnpol@2ka.mipt.ru> wrote:
> On Thu, Apr 20, 2006 at 05:12:33PM +0200, Libor Vanek (libor.vanek@gmail.com) wrote:
>
> > - When sending message from kernel, cn_netlink_send returns an error
> > in case when there is no reciever - BUT user space "send" doesn't
> > return an error when there is no reciever in kernel :-(
>
> Userspace sends it into kernel socket. Groups were created for
> userspace's sockets, so there is always a listener in kernelspace.

OK, I wanted to use this to check, if my module is loaded.

> > - How (if) can I do ACK (acknoledge received and processed message)?
>
> I put seq and ack fields into connector header, and described a simple
> protocol for it's usage, but it does require some work by driver author,
> it is impossible to generate automatic ack messages in netlink
> (well, it is possible to generate nlmsgerr message sending but generally
> it is not what people want with protocols designed over connector).

Problem is that there is no (easy) way how to confirm that message was
recieved and proccessed correctly... OK, I'll have to do it
asynchronous...

> Not a good style of allocating data from atomic pool without checks for
> return value.

Just an simple example...

> Btw, you do not need to allocate it dynamically,
> char msg[sizeof(struct cn_msg) + 32] will work too.

Thanks, I didn't know that one.

> In this example you will receive messages for groups 1, 2 (bind time
> gropus 0x3 is equal to (1<<(1-1)) | (1<<(2-1))) and group 3 (you
> have subscribed to that gropu explicitly).

Thx.

Libor Vanek

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2006-04-20 15:32 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-04-15  1:09 Connector - how to start? Libor Vanek
2006-04-15  2:26 ` Randy.Dunlap
2006-04-15  3:07   ` Matt Helsley
2006-04-15  9:18     ` Evgeniy Polyakov
     [not found]       ` <369a7ef40604150350x8e7dea1sbf1f83cb800dd1c3@mail.gmail.com>
2006-04-15 11:14         ` Evgeniy Polyakov
2006-04-15 12:18           ` Paul Collins
2006-04-15 12:38             ` Evgeniy Polyakov
     [not found]               ` <369a7ef40604150624n28da8895if158a2c13cac2b9e@mail.gmail.com>
2006-04-16  7:53                 ` Evgeniy Polyakov
2006-04-16 17:09                   ` Evgeniy Polyakov
     [not found]       ` <369a7ef40604160426s301dcd52r4c9826698d3d2f79@mail.gmail.com>
2006-04-16 11:40         ` Evgeniy Polyakov
     [not found]           ` <369a7ef40604160509xcf2caadi782b90da956639d5@mail.gmail.com>
2006-04-16 13:25             ` Evgeniy Polyakov
     [not found]               ` <369a7ef40604160632t16f6aab9u687a6b359997d7ea@mail.gmail.com>
2006-04-16 14:19                 ` Evgeniy Polyakov
2006-04-18  6:07                 ` Evgeniy Polyakov
     [not found]                   ` <369a7ef40604190439v6e8f1bf6lf52cfab5af3a93af@mail.gmail.com>
2006-04-19 12:14                     ` Evgeniy Polyakov
2006-04-20 15:12                       ` Libor Vanek
2006-04-20 15:25                         ` Evgeniy Polyakov
2006-04-20 15:32                           ` Libor Vanek
2006-04-15 21:48 ` Jon Masters

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox