X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2FPORTING-DBUS1;h=2dedb28bcfc44b821387c6e088ea1779a3d5941d;hb=1797280193ea25a91cc38332c7cee34ba01e7808;hp=67af27772eec49dcb893aacf143583fdf33b76bb;hpb=607553f9306286fdccf0b356bc3d1087adfe21c4;p=elogind.git diff --git a/src/libsystemd/sd-bus/PORTING-DBUS1 b/src/libsystemd/sd-bus/PORTING-DBUS1 index 67af27772..2dedb28bc 100644 --- a/src/libsystemd/sd-bus/PORTING-DBUS1 +++ b/src/libsystemd/sd-bus/PORTING-DBUS1 @@ -14,11 +14,11 @@ GVariant compatible marshaler to your library first. After you have done that: here's the basic principle how kdbus works: -You connect to a bus by opening its bus node in /dev/kdbus/. All +You connect to a bus by opening its bus node in /sys/fs/kdbus/. All buses have a device node there, it starts with a numeric UID of the owner of the bus, followed by a dash and a string identifying the -bus. The system bus is thus called /dev/kdbus/0-system, and for user -buses the device node is /dev/kdbus/1000-user (if 1000 is your user +bus. The system bus is thus called /sys/fs/kdbus/0-system, and for user +buses the device node is /sys/fs/kdbus/1000-user (if 1000 is your user id). (Before we proceed, please always keep a copy of libsystemd next @@ -51,7 +51,9 @@ client does not know what they mean, it must disconnect. The upper system, the lower 32bit indicate "compatible" feature additions. A client that does not support a "compatible" feature addition can go on communicating with the bus, however a client that does not support an -"incompatible" feature must not proceed with the connection. +"incompatible" feature must not proceed with the connection. When a +client encountes such an "incompatible" feature it should immediately +try the next bus address configured in the bus address string. The hello structure also contains another flags field "attach_flags" which indicates metadata that is optionally attached to all incoming @@ -64,10 +66,11 @@ fields as you need. The kernel will return in the "id" field your unique id. This is a simple numeric value. For compatibility with classic dbus1 simply -format this as string and prefix ":0.". +format this as string and prefix ":1.". -The kernel will also return the bloom filter size used for the signal -broadcast bloom filter (see below). +The kernel will also return the bloom filter size and bloom filter +hash function number used for the signal broadcast bloom filter (see +below). The kernel will also return the bus ID of the bus in a 128bit field. @@ -120,8 +123,8 @@ at the same time! This pretty much explains the ioctl header. The actual payload of the data is now referenced in additional items that are attached to this ioctl header structure at the end. When sending a message, you attach -items of the type PAYLOAD_VEC, PAYLOAD_MEMFD, FDS, BLOOM, DST_NAME to -it: +items of the type PAYLOAD_VEC, PAYLOAD_MEMFD, FDS, BLOOM_FILTER, +DST_NAME to it: KDBUS_ITEM_PAYLOAD_VEC: contains a pointer + length pair for referencing arbitrary user memory. This is how you reference most @@ -131,15 +134,15 @@ it: to send prepared "memfds" (see below) over. This item contains an fd for a memfd plus a size. - KDBUS_ITEM_PAYLOAD_FDS: for sending over fds attach an item of this - type with an array of fds. + KDBUS_ITEM_FDS: for sending over fds attach an item of this type with + an array of fds. - KDBUS_ITEM_BLOOM: the calculated bloom filter of this message, only - for undirected (broadcast) message. + KDBUS_ITEM_BLOOM_FILTER: the calculated bloom filter of this message, + only for undirected (broadcast) message. - KDBUS_DST_NAME: for messages that are directed to a well-known name - (instead of a unique name), this item contains the well-known name - field. + KDBUS_ITEM_DST_NAME: for messages that are directed to a well-known + name (instead of a unique name), this item contains the well-known + name field. A single message may consists of no, one or more payload items of type PAYLOAD_VEC or PAYLOAD_MEMFD. D-Bus protocol implementations should @@ -153,11 +156,11 @@ multiple items. Some restrictions apply however: contained in the payload, as well is immediately before framing of a Gvariant, as well after as any padding bytes if there are any. The padding bytes must be wholly contained in the preceding - PAYLOAD_VEC/PAYLOAD_MEMFD item. You may not split up simple types - nor arrays of trivial types. The latter is necessary to allow APIs - to return direct pointers to linear chunks of fixed size trivial - arrays. Examples: The simple types "u", "s", "t" have to be in the - same payload item. The array of simple types "ay", "ai" have to be + PAYLOAD_VEC/PAYLOAD_MEMFD item. You may not split up basic types + nor arrays of fixed types. The latter is necessary to allow APIs + to return direct pointers to linear arrays of numeric + values. Examples: The basic types "u", "s", "t" have to be in the + same payload item. The array of fixed types "ay", "ai" have to be fully in contained in the same payload item. For an array "as" or "a(si)" the only restriction however is to keep each string individually in an uninterrupted item, to keep the framing of each @@ -172,15 +175,15 @@ which items are contained in the message is left untouched. PAYLOAD_MEMFD items allow zero-copy data transfer (see below regarding the memfd concept). Note however that the overhead of mapping these makes them relatively expensive, and only worth the trouble for memory -blocks > 128K (this value appears to be quite universal across +blocks > 512K (this value appears to be quite universal across architectures, as we tested). Thus we recommend sending PAYLOAD_VEC items over for small messages and restore to PAYLOAD_MEMFD items for -messages > 128K. Since while building up the message you might not +messages > 512K. Since while building up the message you might not know yet whether it will grow beyond this boundary a good approach is to simply build the message unconditionally in a memfd object. However, when the message is sealed to be sent away check for -the size limit. If the size of the message is < 128K, then simply send -the data as PAYLOAD_VEC and reuse the memfd. If it is >= 128K, seal +the size limit. If the size of the message is < 512K, then simply send +the data as PAYLOAD_VEC and reuse the memfd. If it is >= 512K, seal the memfd and send it as PAYLOAD_MEMFD, and allocate a new memfd for the next message. @@ -231,18 +234,35 @@ probabilistically check whether a certain word is contained in a vocabulary. It knows no false negatives, but it does know false positives. -The bloom filter that needs to be included has the parameters m=512 -(bits in the filter), k=8 (nr of hash functions). The underlying hash -function is SipHash-2-4. We calculate two hash values for an input -strings, one with the hash key b9660bf0467047c18875c49c54b9bd15 (this -is supposed to be read as a series of 16 hexadecimal formatted -bytes), and one with the hash key -aaa154a2e0714b39bfe1dd2e9fc54a3b. This results in two 64bit hash -values, A and B. The 8 hash functions for the bloom filter require a 9 -bit output each (since m=512=2^9), to generate these we XOR combine -the first 8 bit of A shifted to the left by 1, with the first 8 bit of -B. Then, for the next hash function we use the second 8 bit pair, and -so on. +The parameters for the bloom filters that need to be included in +broadcast message is communicated to userspace as part of the hello +response structure (see above). By default it has the parameters m=512 +(bits in the filter), k=8 (nr of hash functions). Note however, that +this is subject to change in later versions, and userspace +implementations must be capable of handling m values between at least +m=8 and m=2^32, and k values between at least k=1 and k=32. The +underlying hash function is SipHash-2-4. It is used with a number of +constant (yet originally randomly generated) 128bit hash keys, more +specifically: + + b9,66,0b,f0,46,70,47,c1,88,75,c4,9c,54,b9,bd,15, + aa,a1,54,a2,e0,71,4b,39,bf,e1,dd,2e,9f,c5,4a,3b, + 63,fd,ae,be,cd,82,48,12,a1,6e,41,26,cb,fa,a0,c8, + 23,be,45,29,32,d2,46,2d,82,03,52,28,fe,37,17,f5, + 56,3b,bf,ee,5a,4f,43,39,af,aa,94,08,df,f0,fc,10, + 31,80,c8,73,c7,ea,46,d3,aa,25,75,0f,9e,4c,09,29, + 7d,f7,18,4b,7b,a4,44,d5,85,3c,06,e0,65,53,96,6d, + f2,77,e9,6f,93,b5,4e,71,9a,0c,34,88,39,25,bf,35 + +When calculating the first bit index into the bloom filter, the +SipHash-2-4 hash value is calculated for the input data and the first +16 bytes of the array above as hash key. Of the resulting 8 bytes of +output, as many full bytes are taken for the bit index as necessary, +starting from the output's first byte. For the second bit index the +same hash value is used, continuing with the next unused output byte, +and so on. Each time the bytes returned by the hash function are +depleted it is recalculated with the next 16 byte hash key from the +array above and the same input data. For each message to send across the bus we populate the bloom filter with all possible matchable strings. If a client then wants to @@ -298,6 +318,11 @@ messages (which it needs to anyway, given that transfers are relatively unrestricted on kdbus and people can send you all kinds of non-sense). +If a client connects to a bus whose bloom filter metrics (i.e. filter +size and number of hash functions) are outside of the range the client +supports it must immediately disconnect and continue connection with +the next bus address of the bus connection string. + INSTALLING MATCHES To install matches for broadcast messages, use the KDBUS_CMD_ADD_MATCH @@ -317,7 +342,7 @@ items of the same type as the kernel messages include, i.e. KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE, KDBUS_ITEM_NAME_CHANGE, KDBUS_ITEM_ID_ADD, KDBUS_ITEM_ID_REMOVE and fill them out. Note however, that you have some wildcards in this -case, for example the .id field of KDBUS_ITEM_ADD/KDBUS_ITEM_REMOVE +case, for example the .id field of KDBUS_ITEM_ID_ADD/KDBUS_ITEM_ID_REMOVE structures may be set to 0 to match against any id addition/removal. Note that dbus match strings do no map 1:1 to these ioctl() calls. In @@ -337,46 +362,6 @@ ioctl()s are added for a single match strings. MEMFDS -The "memfd" concept is used for zero-copy data transfers (see -above). memfds are file descriptors to memory chunks of arbitrary -sizes. If you have a memfd you can mmap() it to get access to the data -it contains or write to it. They are comparable to file descriptors to -unlinked files on a tmpfs, or to anonymous memory that one may refer -to with an fd. They have one particular property: they can be -"sealed". A memfd that is "sealed" is protected from alteration. Only -memfds that are currently not mapped and to which a single fd refers -may be sealed (they may also be unsealed in that case). - -The concept of "sealing" makes memfds useful for using them as -transport for kdbus messages: only when the receiver knows that the -message it has received cannot change while looking at, it can safely -parse it without having to copy it to a safe memory area. memfds can also -be reused in multiple messages. A sender may send the same memfd to -multiple peers, and since it is sealed, it can be sure that the receiver -will not be able to modify it. "Sealing" hence provides both sides of -a transaction with the guarantee that the data stays constant and is -reusable. - -memfds are a generic concept that can be used outside of the immediate -kdbus usecase. You can send them across AF_UNIX sockets too, sealed or -unsealed. In kdbus themselves, they can be used to send zero-copy -payloads, but may also be sent as normal fds. - -memfds are allocated with the KDBUS_CMD_MEMFD_NEW ioctl. After allocation, -simply memory map them and write to them. To set their size, use -KDBUS_CMD_MEMFD_SIZE_SET. Note that memfds will be increased in size -automatically if you touch previously unallocated pages. However, the -size will only be increased in multiples of the page size in that -case. Thus, in almost all cases, an explicit KDBUS_CMD_MEMFD_SIZE_SET -is necessary, since it allows setting memfd sizes in finer -granularity. To seal a memfd use the KDBUS_CMD_MEMFD_SEAL_SET ioctl -call. It will only succeed if the caller has the only fd reference to -the memfd open, and if the memfd is currently unmapped. - -If memfds are shared, keep in mind that the file pointer used by -write/read/seek is shared too, only pread/pwrite are safe to use -in that case. - memfds may be sent across kdbus via KDBUS_ITEM_PAYLOAD_MEMFD items attached to messages. If this is done, the data included in the memfd is considered part of the payload stream of a message, and are treated @@ -483,7 +468,7 @@ have attached. Note that when issuing the ioctl, you can select a different set of credentials to gather, than what was originally requested for being attached to incoming messages. -Credentials are always specific to the sender namespace that was +Credentials are always specific to the sender's domain that was current at the time of sending, and of the process that opened the bus connection at the time of opening it. Note that this latter data is cached! @@ -511,12 +496,12 @@ parameter. Client libraries should use the following connection string when connecting to the system bus: - kernel:path=/dev/kdbus/0-system/bus;unix:path=/run/dbus/system_bus_socket + kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket This will ensure that kdbus is preferred over the legacy AF_UNIX socket, but compatibility is kept. For the user bus use: - kernel:path=/dev/kdbus/$UID-user/bus;unix:path=$XDG_RUNTIME_DIR/bus + kernel:path=/sys/fs/kdbus/$UID-user/bus;unix:path=$XDG_RUNTIME_DIR/bus With $UID replaced by the callers numer user ID, and $XDG_RUNTIME_DIR following the XDG basedir spec.