Netlink notifier chain

At Collabora we are working on improving the D-Bus IPC system. We are trying different approaches and one of them is implementing the D-Bus routing logic and match rules handling as a Generic Netlink service. Rodrigo wrote a great blog entry on the design of this Netlink solution.

A problem we found is that AF_NETLINK is not connection oriented. Applications don’t establish a connection before transmitting, they just open a socket and start sending messages. So, if an application close its socket, the other peers won’t notice. This also applies to the kernel code since in Generic Netlink, the in kernel service is just another user of the Netlink channel.

The problem is that D-bus is connection oriented, we have to keep track of each connection to the bus and remove it when the socket associate with the connection is closed.

Fortunately, the kernel has a mechanism known as notifier chains that allows kernel code to listen for certain events by registering to a specific notifier chain.

Netlink defines a notifier netlink_chain to notify when a socket is released (NETLINK_URELEASE event). So, we can use that information to remove the D-Bus connection associate with a socket when it is released.

The notifier API is very simple, we only have to define a notifier_block data structure and assign a function handler to the notifier_call function pointer. Once the notifier_block data structure is registered, the notifier_call function handler is called every time the events occurs.

I knew about notifier chains before but haven’t used until today so I thought it was something interesting to share. Here is a small example of how we can use the Netlink notifier chain:

static int dbus_netlink_notify(struct notifier_block *nb, unsigned long state,
                               void *_notify)
{
        struct netlink_notify *notify = _notify;

        if (state == NETLINK_URELEASE && notify->protocol == NETLINK_GENERIC)
                dbus_bus_del_connection(notify->pid);

        return NOTIFY_DONE;
}

static struct notifier_block dbus_netlink_notifier = {
	.notifier_call = dbus_netlink_notify,
};

static int __init dbus_init(void)
{
	int rc;

	rc = genl_register_family_with_ops(&dbus_family, dbus_ops,
					   ARRAY_SIZE(dbus_ops));
	if (rc)
                return rc;

	rc = netlink_register_notifier(&dbus_netlink_notifier);
	if (rc) {
                genl_unregister_family(&dbus_family);
                return rc;
	}

	return 0;
}
About these ads
This entry was posted in Uncategorized and tagged . Bookmark the permalink.

2 Responses to Netlink notifier chain

  1. Raul says:

    Where are dbus_family and dbus_ops defined?

  2. Javier Martinez Canillas says:

    They are defined above. I didn’t show all the Netlink code of the Generic Netlink dbus family for the sake of simplicity, only the code relevant to the notifier chain.

    This is how dbus_family (the Generic Netlink family for dbus) and dbus_ops (the Generic Netlink operations) are defined:

    
    static struct genl_family dbus_family = {
    	.id = GENL_ID_GENERATE,
    	.hdrsize = 0,
    	.name = "dbus",
    	.version = 1,
    	.maxattr = DBUS_ATTR_MAX,
    };
    
    static struct genl_ops dbus_ops[] = {
    	{
    		.cmd = DBUS_CMD_ADDBUS,
    		.policy = dbus_policy,
    		.doit = dbus_add_bus,
    	},
    	{
    		.cmd = DBUS_CMD_DELBUS,
    		.policy = dbus_policy,
    		.doit = dbus_del_bus,
    	},
    	{
    		.cmd = DBUS_CMD_CONBUS,
    		.policy = dbus_policy,
    		.doit = dbus_con_bus,
    	},
    	{
    		.cmd = DBUS_CMD_DISBUS,
    		.policy = dbus_policy,
    		.doit = dbus_dis_bus,
    	},
    };
    
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s