From 720594f691e5c8fb0624f3653b20b24ba8e57742 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sat, 13 Apr 2019 22:54:53 -0300 Subject: docs: connector: convert to ReST and rename to connector.rst As it has some function definitions, move them to connector.h. The remaining conversion is actually: - add blank lines and identation in order to identify paragraphs; - fix tables markups; - add some lists markups; - mark literal blocks; - adjust title markups. At its new index.rst, let's add a :orphan: while this is not linked to the main index.rst file, in order to avoid build warnings. Signed-off-by: Mauro Carvalho Chehab --- Documentation/connector/connector.rst | 156 +++++++++++++++++++++++++++ Documentation/connector/connector.txt | 196 ---------------------------------- drivers/w1/Kconfig | 2 +- include/linux/connector.h | 63 ++++++++++- samples/Kconfig | 2 +- 5 files changed, 220 insertions(+), 199 deletions(-) create mode 100644 Documentation/connector/connector.rst delete mode 100644 Documentation/connector/connector.txt diff --git a/Documentation/connector/connector.rst b/Documentation/connector/connector.rst new file mode 100644 index 000000000000..24e26dc22dbf --- /dev/null +++ b/Documentation/connector/connector.rst @@ -0,0 +1,156 @@ +:orphan: + +================ +Kernel Connector +================ + +Kernel connector - new netlink based userspace <-> kernel space easy +to use communication module. + +The Connector driver makes it easy to connect various agents using a +netlink based network. One must register a callback and an identifier. +When the driver receives a special netlink message with the appropriate +identifier, the appropriate callback will be called. + +From the userspace point of view it's quite straightforward: + + - socket(); + - bind(); + - send(); + - recv(); + +But if kernelspace wants to use the full power of such connections, the +driver writer must create special sockets, must know about struct sk_buff +handling, etc... The Connector driver allows any kernelspace agents to use +netlink based networking for inter-process communication in a significantly +easier way:: + + int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *)); + void cn_netlink_send_multi(struct cn_msg *msg, u16 len, u32 portid, u32 __group, int gfp_mask); + void cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group, int gfp_mask); + + struct cb_id + { + __u32 idx; + __u32 val; + }; + +idx and val are unique identifiers which must be registered in the +connector.h header for in-kernel usage. `void (*callback) (void *)` is a +callback function which will be called when a message with above idx.val +is received by the connector core. The argument for that function must +be dereferenced to `struct cn_msg *`:: + + struct cn_msg + { + struct cb_id id; + + __u32 seq; + __u32 ack; + + __u32 len; /* Length of the following data */ + __u8 data[0]; + }; + +Connector interfaces +==================== + + .. kernel-doc:: include/linux/connector.h + + Note: + When registering new callback user, connector core assigns + netlink group to the user which is equal to its id.idx. + +Protocol description +==================== + +The current framework offers a transport layer with fixed headers. The +recommended protocol which uses such a header is as following: + +msg->seq and msg->ack are used to determine message genealogy. When +someone sends a message, they use a locally unique sequence and random +acknowledge number. The sequence number may be copied into +nlmsghdr->nlmsg_seq too. + +The sequence number is incremented with each message sent. + +If you expect a reply to the message, then the sequence number in the +received message MUST be the same as in the original message, and the +acknowledge number MUST be the same + 1. + +If we receive a message and its sequence number is not equal to one we +are expecting, then it is a new message. If we receive a message and +its sequence number is the same as one we are expecting, but its +acknowledge is not equal to the sequence number in the original +message + 1, then it is a new message. + +Obviously, the protocol header contains the above id. + +The connector allows event notification in the following form: kernel +driver or userspace process can ask connector to notify it when +selected ids will be turned on or off (registered or unregistered its +callback). It is done by sending a special command to the connector +driver (it also registers itself with id={-1, -1}). + +As example of this usage can be found in the cn_test.c module which +uses the connector to request notification and to send messages. + +Reliability +=========== + +Netlink itself is not a reliable protocol. That means that messages can +be lost due to memory pressure or process' receiving queue overflowed, +so caller is warned that it must be prepared. That is why the struct +cn_msg [main connector's message header] contains u32 seq and u32 ack +fields. + +Userspace usage +=============== + +2.6.14 has a new netlink socket implementation, which by default does not +allow people to send data to netlink groups other than 1. +So, if you wish to use a netlink socket (for example using connector) +with a different group number, the userspace application must subscribe to +that group first. It can be achieved by the following pseudocode:: + + s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + + l_local.nl_family = AF_NETLINK; + l_local.nl_groups = 12345; + l_local.nl_pid = 0; + + if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { + perror("bind"); + close(s); + return -1; + } + + { + int on = l_local.nl_groups; + setsockopt(s, 270, 1, &on, sizeof(on)); + } + +Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket +option. To drop a multicast subscription, one should call the above socket +option with the NETLINK_DROP_MEMBERSHIP parameter which is defined as 0. + +2.6.14 netlink code only allows to select a group which is less or equal to +the maximum group number, which is used at netlink_kernel_create() time. +In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use +group number 12345, you must increment CN_NETLINK_USERS to that number. +Additional 0xf numbers are allocated to be used by non-in-kernel users. + +Due to this limitation, group 0xffffffff does not work now, so one can +not use add/remove connector's group notifications, but as far as I know, +only cn_test.c test module used it. + +Some work in netlink area is still being done, so things can be changed in +2.6.15 timeframe, if it will happen, documentation will be updated for that +kernel. + +Code samples +============ + +Sample code for a connector test module and user space can be found +in samples/connector/. To build this code, enable CONFIG_CONNECTOR +and CONFIG_SAMPLES. diff --git a/Documentation/connector/connector.txt b/Documentation/connector/connector.txt deleted file mode 100644 index ab7ca897fab7..000000000000 --- a/Documentation/connector/connector.txt +++ /dev/null @@ -1,196 +0,0 @@ -/*****************************************/ -Kernel Connector. -/*****************************************/ - -Kernel connector - new netlink based userspace <-> kernel space easy -to use communication module. - -The Connector driver makes it easy to connect various agents using a -netlink based network. One must register a callback and an identifier. -When the driver receives a special netlink message with the appropriate -identifier, the appropriate callback will be called. - -From the userspace point of view it's quite straightforward: - - socket(); - bind(); - send(); - recv(); - -But if kernelspace wants to use the full power of such connections, the -driver writer must create special sockets, must know about struct sk_buff -handling, etc... The Connector driver allows any kernelspace agents to use -netlink based networking for inter-process communication in a significantly -easier way: - -int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *)); -void cn_netlink_send_multi(struct cn_msg *msg, u16 len, u32 portid, u32 __group, int gfp_mask); -void cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __group, int gfp_mask); - -struct cb_id -{ - __u32 idx; - __u32 val; -}; - -idx and val are unique identifiers which must be registered in the -connector.h header for in-kernel usage. void (*callback) (void *) is a -callback function which will be called when a message with above idx.val -is received by the connector core. The argument for that function must -be dereferenced to struct cn_msg *. - -struct cn_msg -{ - struct cb_id id; - - __u32 seq; - __u32 ack; - - __u32 len; /* Length of the following data */ - __u8 data[0]; -}; - -/*****************************************/ -Connector interfaces. -/*****************************************/ - -int cn_add_callback(struct cb_id *id, char *name, void (*callback) (struct cn_msg *, struct netlink_skb_parms *)); - - Registers new callback with connector core. - - struct cb_id *id - unique connector's user identifier. - It must be registered in connector.h for legal in-kernel users. - char *name - connector's callback symbolic name. - void (*callback) (struct cn..) - connector's callback. - cn_msg and the sender's credentials - - -void cn_del_callback(struct cb_id *id); - - Unregisters new callback with connector core. - - struct cb_id *id - unique connector's user identifier. - - -int cn_netlink_send_multi(struct cn_msg *msg, u16 len, u32 portid, u32 __groups, int gfp_mask); -int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 __groups, int gfp_mask); - - Sends message to the specified groups. It can be safely called from - softirq context, but may silently fail under strong memory pressure. - If there are no listeners for given group -ESRCH can be returned. - - struct cn_msg * - message header(with attached data). - u16 len - for *_multi multiple cn_msg messages can be sent - u32 port - destination port. - If non-zero the message will be sent to the - given port, which should be set to the - original sender. - u32 __group - destination group. - If port and __group is zero, then appropriate group will - be searched through all registered connector users, - and message will be delivered to the group which was - created for user with the same ID as in msg. - If __group is not zero, then message will be delivered - to the specified group. - int gfp_mask - GFP mask. - - Note: When registering new callback user, connector core assigns - netlink group to the user which is equal to its id.idx. - -/*****************************************/ -Protocol description. -/*****************************************/ - -The current framework offers a transport layer with fixed headers. The -recommended protocol which uses such a header is as following: - -msg->seq and msg->ack are used to determine message genealogy. When -someone sends a message, they use a locally unique sequence and random -acknowledge number. The sequence number may be copied into -nlmsghdr->nlmsg_seq too. - -The sequence number is incremented with each message sent. - -If you expect a reply to the message, then the sequence number in the -received message MUST be the same as in the original message, and the -acknowledge number MUST be the same + 1. - -If we receive a message and its sequence number is not equal to one we -are expecting, then it is a new message. If we receive a message and -its sequence number is the same as one we are expecting, but its -acknowledge is not equal to the sequence number in the original -message + 1, then it is a new message. - -Obviously, the protocol header contains the above id. - -The connector allows event notification in the following form: kernel -driver or userspace process can ask connector to notify it when -selected ids will be turned on or off (registered or unregistered its -callback). It is done by sending a special command to the connector -driver (it also registers itself with id={-1, -1}). - -As example of this usage can be found in the cn_test.c module which -uses the connector to request notification and to send messages. - -/*****************************************/ -Reliability. -/*****************************************/ - -Netlink itself is not a reliable protocol. That means that messages can -be lost due to memory pressure or process' receiving queue overflowed, -so caller is warned that it must be prepared. That is why the struct -cn_msg [main connector's message header] contains u32 seq and u32 ack -fields. - -/*****************************************/ -Userspace usage. -/*****************************************/ - -2.6.14 has a new netlink socket implementation, which by default does not -allow people to send data to netlink groups other than 1. -So, if you wish to use a netlink socket (for example using connector) -with a different group number, the userspace application must subscribe to -that group first. It can be achieved by the following pseudocode: - -s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); - -l_local.nl_family = AF_NETLINK; -l_local.nl_groups = 12345; -l_local.nl_pid = 0; - -if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { - perror("bind"); - close(s); - return -1; -} - -{ - int on = l_local.nl_groups; - setsockopt(s, 270, 1, &on, sizeof(on)); -} - -Where 270 above is SOL_NETLINK, and 1 is a NETLINK_ADD_MEMBERSHIP socket -option. To drop a multicast subscription, one should call the above socket -option with the NETLINK_DROP_MEMBERSHIP parameter which is defined as 0. - -2.6.14 netlink code only allows to select a group which is less or equal to -the maximum group number, which is used at netlink_kernel_create() time. -In case of connector it is CN_NETLINK_USERS + 0xf, so if you want to use -group number 12345, you must increment CN_NETLINK_USERS to that number. -Additional 0xf numbers are allocated to be used by non-in-kernel users. - -Due to this limitation, group 0xffffffff does not work now, so one can -not use add/remove connector's group notifications, but as far as I know, -only cn_test.c test module used it. - -Some work in netlink area is still being done, so things can be changed in -2.6.15 timeframe, if it will happen, documentation will be updated for that -kernel. - -/*****************************************/ -Code samples -/*****************************************/ - -Sample code for a connector test module and user space can be found -in samples/connector/. To build this code, enable CONFIG_CONNECTOR -and CONFIG_SAMPLES. diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 03dd57581df7..160053c0baea 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -19,7 +19,7 @@ config W1_CON default y ---help--- This allows to communicate with userspace using connector. For more - information see . + information see . There are three types of messages between w1 core and userspace: 1. Events. They are generated each time new master or slave device found either due to automatic or requested search. diff --git a/include/linux/connector.h b/include/linux/connector.h index 1d72ef76f24f..6b6c7396a584 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -55,10 +55,71 @@ struct cn_dev { struct cn_queue_dev *cbdev; }; +/** + * cn_add_callback() - Registers new callback with connector core. + * + * @id: unique connector's user identifier. + * It must be registered in connector.h for legal + * in-kernel users. + * @name: connector's callback symbolic name. + * @callback: connector's callback. + * parameters are %cn_msg and the sender's credentials + */ int cn_add_callback(struct cb_id *id, const char *name, void (*callback)(struct cn_msg *, struct netlink_skb_parms *)); -void cn_del_callback(struct cb_id *); +/** + * cn_del_callback() - Unregisters new callback with connector core. + * + * @id: unique connector's user identifier. + */ +void cn_del_callback(struct cb_id *id); + + +/** + * cn_netlink_send_mult - Sends message to the specified groups. + * + * @msg: message header(with attached data). + * @len: Number of @msg to be sent. + * @portid: destination port. + * If non-zero the message will be sent to the given port, + * which should be set to the original sender. + * @group: destination group. + * If @portid and @group is zero, then appropriate group will + * be searched through all registered connector users, and + * message will be delivered to the group which was created + * for user with the same ID as in @msg. + * If @group is not zero, then message will be delivered + * to the specified group. + * @gfp_mask: GFP mask. + * + * It can be safely called from softirq context, but may silently + * fail under strong memory pressure. + * + * If there are no listeners for given group %-ESRCH can be returned. + */ int cn_netlink_send_mult(struct cn_msg *msg, u16 len, u32 portid, u32 group, gfp_t gfp_mask); + +/** + * cn_netlink_send_mult - Sends message to the specified groups. + * + * @msg: message header(with attached data). + * @portid: destination port. + * If non-zero the message will be sent to the given port, + * which should be set to the original sender. + * @group: destination group. + * If @portid and @group is zero, then appropriate group will + * be searched through all registered connector users, and + * message will be delivered to the group which was created + * for user with the same ID as in @msg. + * If @group is not zero, then message will be delivered + * to the specified group. + * @gfp_mask: GFP mask. + * + * It can be safely called from softirq context, but may silently + * fail under strong memory pressure. + * + * If there are no listeners for given group %-ESRCH can be returned. + */ int cn_netlink_send(struct cn_msg *msg, u32 portid, u32 group, gfp_t gfp_mask); int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name, diff --git a/samples/Kconfig b/samples/Kconfig index 71b5e833dd9e..155da47dc6a4 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -99,7 +99,7 @@ config SAMPLE_CONNECTOR When enabled, this builds both a sample kernel module for the connector interface and a user space tool to communicate with it. - See also Documentation/connector/connector.txt + See also Documentation/connector/connector.rst config SAMPLE_HIDRAW bool "hidraw sample" -- cgit v1.2.3-55-g7522