mirror of
https://github.com/openvswitch/ovs
synced 2025-09-01 06:45:17 +00:00
notifiers: Create and destroy nln_notifiers.
This patch changes the interface of netlink-notifier and rtnetlink-link. Now nln_notifiers are allocated and destroyed by the module instead of passed in by callers. This allows the definition of nln_notifier to be hidden, and generally cleans up the code.
This commit is contained in:
@@ -137,7 +137,7 @@ struct dpif_linux {
|
|||||||
|
|
||||||
/* Change notification. */
|
/* Change notification. */
|
||||||
struct sset changed_ports; /* Ports that have changed. */
|
struct sset changed_ports; /* Ports that have changed. */
|
||||||
struct nln_notifier port_notifier;
|
struct nln_notifier *port_notifier;
|
||||||
bool change_error;
|
bool change_error;
|
||||||
|
|
||||||
/* Queue of unused ports. */
|
/* Queue of unused ports. */
|
||||||
@@ -253,13 +253,12 @@ static int
|
|||||||
open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp)
|
open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp)
|
||||||
{
|
{
|
||||||
struct dpif_linux *dpif;
|
struct dpif_linux *dpif;
|
||||||
int error;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
dpif = xmalloc(sizeof *dpif);
|
dpif = xmalloc(sizeof *dpif);
|
||||||
error = nln_notifier_register(nln, &dpif->port_notifier,
|
dpif->port_notifier = nln_notifier_create(nln, dpif_linux_port_changed,
|
||||||
dpif_linux_port_changed, dpif);
|
dpif);
|
||||||
if (error) {
|
if (!dpif->port_notifier) {
|
||||||
goto error_free;
|
goto error_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,7 +285,7 @@ open_dpif(const struct dpif_linux_dp *dp, struct dpif **dpifp)
|
|||||||
|
|
||||||
error_free:
|
error_free:
|
||||||
free(dpif);
|
free(dpif);
|
||||||
return error;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -294,10 +293,7 @@ dpif_linux_close(struct dpif *dpif_)
|
|||||||
{
|
{
|
||||||
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
struct dpif_linux *dpif = dpif_linux_cast(dpif_);
|
||||||
|
|
||||||
if (nln) {
|
nln_notifier_destroy(dpif->port_notifier);
|
||||||
nln_notifier_unregister(nln, &dpif->port_notifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
nl_sock_destroy(dpif->mc_sock);
|
nl_sock_destroy(dpif->mc_sock);
|
||||||
sset_destroy(&dpif->changed_ports);
|
sset_destroy(&dpif->changed_ports);
|
||||||
free(dpif->lru_bitmap);
|
free(dpif->lru_bitmap);
|
||||||
|
@@ -105,7 +105,7 @@ COVERAGE_DEFINE(netdev_ethtool);
|
|||||||
#define TC_RTAB_SIZE 1024
|
#define TC_RTAB_SIZE 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct nln_notifier netdev_linux_cache_notifier;
|
static struct nln_notifier *netdev_linux_cache_notifier = NULL;
|
||||||
static int cache_notifier_refcount;
|
static int cache_notifier_refcount;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -526,13 +526,15 @@ netdev_linux_create(const struct netdev_class *class, const char *name,
|
|||||||
struct netdev_dev **netdev_devp)
|
struct netdev_dev **netdev_devp)
|
||||||
{
|
{
|
||||||
struct netdev_dev_linux *netdev_dev;
|
struct netdev_dev_linux *netdev_dev;
|
||||||
int error;
|
|
||||||
|
|
||||||
if (!cache_notifier_refcount) {
|
if (!cache_notifier_refcount) {
|
||||||
error = rtnetlink_link_notifier_register(&netdev_linux_cache_notifier,
|
assert(!netdev_linux_cache_notifier);
|
||||||
netdev_linux_cache_cb, NULL);
|
|
||||||
if (error) {
|
netdev_linux_cache_notifier =
|
||||||
return error;
|
rtnetlink_link_notifier_create(netdev_linux_cache_cb, NULL);
|
||||||
|
|
||||||
|
if (!netdev_linux_cache_notifier) {
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache_notifier_refcount++;
|
cache_notifier_refcount++;
|
||||||
@@ -622,7 +624,9 @@ netdev_linux_destroy(struct netdev_dev *netdev_dev_)
|
|||||||
cache_notifier_refcount--;
|
cache_notifier_refcount--;
|
||||||
|
|
||||||
if (!cache_notifier_refcount) {
|
if (!cache_notifier_refcount) {
|
||||||
rtnetlink_link_notifier_unregister(&netdev_linux_cache_notifier);
|
assert(netdev_linux_cache_notifier);
|
||||||
|
rtnetlink_link_notifier_destroy(netdev_linux_cache_notifier);
|
||||||
|
netdev_linux_cache_notifier = NULL;
|
||||||
}
|
}
|
||||||
} else if (class == &netdev_tap_class) {
|
} else if (class == &netdev_tap_class) {
|
||||||
destroy_tap(netdev_dev);
|
destroy_tap(netdev_dev);
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "netlink-notifier.h"
|
#include "netlink-notifier.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -46,6 +47,14 @@ struct nln {
|
|||||||
void *change; /* Change passed to parse. */
|
void *change; /* Change passed to parse. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nln_notifier {
|
||||||
|
struct nln *nln; /* Parent nln. */
|
||||||
|
|
||||||
|
struct list node;
|
||||||
|
nln_notify_func *cb;
|
||||||
|
void *aux;
|
||||||
|
};
|
||||||
|
|
||||||
/* Creates an nln handle which may be used to manage change notifications. The
|
/* Creates an nln handle which may be used to manage change notifications. The
|
||||||
* created handle will listen for netlink messages on 'multicast_group' using
|
* created handle will listen for netlink messages on 'multicast_group' using
|
||||||
* netlink protocol 'protocol' (e.g. NETLINK_ROUTE, NETLINK_GENERIC, ...).
|
* netlink protocol 'protocol' (e.g. NETLINK_ROUTE, NETLINK_GENERIC, ...).
|
||||||
@@ -70,11 +79,15 @@ nln_create(int protocol, int multicast_group, nln_parse_func *parse,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Destroys 'nln' by freeing any memory it has reserved and closing any sockets
|
/* Destroys 'nln' by freeing any memory it has reserved and closing any sockets
|
||||||
* it has opened. */
|
* it has opened.
|
||||||
|
*
|
||||||
|
* The caller is responsible for destroying any notifiers created by this
|
||||||
|
* 'nln' before destroying 'nln'. */
|
||||||
void
|
void
|
||||||
nln_destroy(struct nln *nln)
|
nln_destroy(struct nln *nln)
|
||||||
{
|
{
|
||||||
if (nln) {
|
if (nln) {
|
||||||
|
assert(list_is_empty(&nln->all_notifiers));
|
||||||
nl_sock_destroy(nln->notify_sock);
|
nl_sock_destroy(nln->notify_sock);
|
||||||
free(nln);
|
free(nln);
|
||||||
}
|
}
|
||||||
@@ -87,11 +100,12 @@ nln_destroy(struct nln *nln)
|
|||||||
* This is probably not the function you want. You should probably be using
|
* This is probably not the function you want. You should probably be using
|
||||||
* message specific notifiers like rtnetlink_link_notifier_register().
|
* message specific notifiers like rtnetlink_link_notifier_register().
|
||||||
*
|
*
|
||||||
* Returns 0 if successful, otherwise a positive errno value. */
|
* Returns an initialized nln_notifier if successful, otherwise NULL. */
|
||||||
int
|
struct nln_notifier *
|
||||||
nln_notifier_register(struct nln *nln, struct nln_notifier *notifier,
|
nln_notifier_create(struct nln *nln, nln_notify_func *cb, void *aux)
|
||||||
nln_notify_func *cb, void *aux)
|
|
||||||
{
|
{
|
||||||
|
struct nln_notifier *notifier;
|
||||||
|
|
||||||
if (!nln->notify_sock) {
|
if (!nln->notify_sock) {
|
||||||
struct nl_sock *sock;
|
struct nl_sock *sock;
|
||||||
int error;
|
int error;
|
||||||
@@ -103,7 +117,7 @@ nln_notifier_register(struct nln *nln, struct nln_notifier *notifier,
|
|||||||
if (error) {
|
if (error) {
|
||||||
nl_sock_destroy(sock);
|
nl_sock_destroy(sock);
|
||||||
VLOG_WARN("could not create netlink socket: %s", strerror(error));
|
VLOG_WARN("could not create netlink socket: %s", strerror(error));
|
||||||
return error;
|
return NULL;
|
||||||
}
|
}
|
||||||
nln->notify_sock = sock;
|
nln->notify_sock = sock;
|
||||||
} else {
|
} else {
|
||||||
@@ -112,22 +126,29 @@ nln_notifier_register(struct nln *nln, struct nln_notifier *notifier,
|
|||||||
nln_run(nln);
|
nln_run(nln);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifier = xmalloc(sizeof *notifier);
|
||||||
list_push_back(&nln->all_notifiers, ¬ifier->node);
|
list_push_back(&nln->all_notifiers, ¬ifier->node);
|
||||||
notifier->cb = cb;
|
notifier->cb = cb;
|
||||||
notifier->aux = aux;
|
notifier->aux = aux;
|
||||||
return 0;
|
notifier->nln = nln;
|
||||||
|
return notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancels notification on 'notifier', which must have previously been
|
/* Destroys 'notifier', which must have previously been created with
|
||||||
* registered with nln_notifier_register(). */
|
* nln_notifier_register(). */
|
||||||
void
|
void
|
||||||
nln_notifier_unregister(struct nln *nln, struct nln_notifier *notifier)
|
nln_notifier_destroy(struct nln_notifier *notifier)
|
||||||
{
|
{
|
||||||
|
if (notifier) {
|
||||||
|
struct nln *nln = notifier->nln;
|
||||||
|
|
||||||
list_remove(¬ifier->node);
|
list_remove(¬ifier->node);
|
||||||
if (list_is_empty(&nln->all_notifiers)) {
|
if (list_is_empty(&nln->all_notifiers)) {
|
||||||
nl_sock_destroy(nln->notify_sock);
|
nl_sock_destroy(nln->notify_sock);
|
||||||
nln->notify_sock = NULL;
|
nln->notify_sock = NULL;
|
||||||
}
|
}
|
||||||
|
free(notifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calls all of the registered notifiers, passing along any as-yet-unreported
|
/* Calls all of the registered notifiers, passing along any as-yet-unreported
|
||||||
|
@@ -23,6 +23,8 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
struct nln;
|
struct nln;
|
||||||
|
struct nln_notifier;
|
||||||
|
|
||||||
struct nlattr;
|
struct nlattr;
|
||||||
struct ofpbuf;
|
struct ofpbuf;
|
||||||
|
|
||||||
@@ -37,18 +39,12 @@ typedef void nln_notify_func(const void *change, void *aux);
|
|||||||
* should be parsed into 'change' as specified in nln_create(). */
|
* should be parsed into 'change' as specified in nln_create(). */
|
||||||
typedef bool nln_parse_func(struct ofpbuf *buf, void *change);
|
typedef bool nln_parse_func(struct ofpbuf *buf, void *change);
|
||||||
|
|
||||||
struct nln_notifier {
|
|
||||||
struct list node;
|
|
||||||
nln_notify_func *cb;
|
|
||||||
void *aux;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct nln *nln_create(int protocol, int multicast_group, nln_parse_func *,
|
struct nln *nln_create(int protocol, int multicast_group, nln_parse_func *,
|
||||||
void *change);
|
void *change);
|
||||||
void nln_destroy(struct nln *);
|
void nln_destroy(struct nln *);
|
||||||
int nln_notifier_register(struct nln *, struct nln_notifier *,
|
struct nln_notifier *nln_notifier_create(struct nln *, nln_notify_func *,
|
||||||
nln_notify_func *, void *aux);
|
void *aux);
|
||||||
void nln_notifier_unregister(struct nln *, struct nln_notifier *);
|
void nln_notifier_destroy(struct nln_notifier *);
|
||||||
void nln_run(struct nln *);
|
void nln_run(struct nln *);
|
||||||
void nln_wait(struct nln *);
|
void nln_wait(struct nln *);
|
||||||
#endif /* netlink-notifier.h */
|
#endif /* netlink-notifier.h */
|
||||||
|
@@ -69,8 +69,8 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
|
|||||||
static unsigned int register_count = 0;
|
static unsigned int register_count = 0;
|
||||||
static struct nln *nln = NULL;
|
static struct nln *nln = NULL;
|
||||||
static struct route_table_msg rtmsg;
|
static struct route_table_msg rtmsg;
|
||||||
static struct nln_notifier route_notifier;
|
static struct nln_notifier *route_notifier = NULL;
|
||||||
static struct nln_notifier name_notifier;
|
static struct nln_notifier *name_notifier = NULL;
|
||||||
|
|
||||||
static bool route_table_valid = false;
|
static bool route_table_valid = false;
|
||||||
static bool name_table_valid = false;
|
static bool name_table_valid = false;
|
||||||
@@ -162,11 +162,14 @@ route_table_register(void)
|
|||||||
{
|
{
|
||||||
if (!register_count) {
|
if (!register_count) {
|
||||||
assert(!nln);
|
assert(!nln);
|
||||||
|
assert(!route_notifier);
|
||||||
|
|
||||||
nln = nln_create(NETLINK_ROUTE, RTNLGRP_IPV4_ROUTE,
|
nln = nln_create(NETLINK_ROUTE, RTNLGRP_IPV4_ROUTE,
|
||||||
(nln_parse_func *) route_table_parse, &rtmsg);
|
(nln_parse_func *) route_table_parse, &rtmsg);
|
||||||
nln_notifier_register(nln, &route_notifier,
|
|
||||||
(nln_notify_func *) route_table_change, NULL);
|
route_notifier =
|
||||||
|
nln_notifier_create(nln, (nln_notify_func *) route_table_change,
|
||||||
|
NULL);
|
||||||
|
|
||||||
hmap_init(&route_map);
|
hmap_init(&route_map);
|
||||||
route_table_reset();
|
route_table_reset();
|
||||||
@@ -396,14 +399,15 @@ static void
|
|||||||
name_table_init(void)
|
name_table_init(void)
|
||||||
{
|
{
|
||||||
hmap_init(&name_map);
|
hmap_init(&name_map);
|
||||||
rtnetlink_link_notifier_register(&name_notifier, name_table_change, NULL);
|
name_notifier = rtnetlink_link_notifier_create(name_table_change, NULL);
|
||||||
name_table_valid = false;
|
name_table_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
name_table_uninit(void)
|
name_table_uninit(void)
|
||||||
{
|
{
|
||||||
rtnetlink_link_notifier_unregister(&name_notifier);
|
rtnetlink_link_notifier_destroy(name_notifier);
|
||||||
|
name_notifier = NULL;
|
||||||
name_map_clear();
|
name_map_clear();
|
||||||
hmap_destroy(&name_map);
|
hmap_destroy(&name_map);
|
||||||
}
|
}
|
||||||
|
@@ -85,25 +85,24 @@ rtnetlink_link_parse_cb(struct ofpbuf *buf, void *change)
|
|||||||
* using dpif_port_poll() or netdev_change_seq(), which unlike this function
|
* using dpif_port_poll() or netdev_change_seq(), which unlike this function
|
||||||
* are not Linux-specific.
|
* are not Linux-specific.
|
||||||
*
|
*
|
||||||
* Returns 0 if successful, otherwise a positive errno value. */
|
* Returns an initialized nln_notifier if successful, NULL otherwise. */
|
||||||
int
|
struct nln_notifier *
|
||||||
rtnetlink_link_notifier_register(struct nln_notifier *notifier,
|
rtnetlink_link_notifier_create(rtnetlink_link_notify_func *cb, void *aux)
|
||||||
rtnetlink_link_notify_func *cb, void *aux)
|
|
||||||
{
|
{
|
||||||
if (!nln) {
|
if (!nln) {
|
||||||
nln = nln_create(NETLINK_ROUTE, RTNLGRP_LINK, rtnetlink_link_parse_cb,
|
nln = nln_create(NETLINK_ROUTE, RTNLGRP_LINK, rtnetlink_link_parse_cb,
|
||||||
&rtn_change);
|
&rtn_change);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nln_notifier_register(nln, notifier, (nln_notify_func *) cb, aux);
|
return nln_notifier_create(nln, (nln_notify_func *) cb, aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancels notification on 'notifier', which must have previously been
|
/* Destroys 'notifier', which must have previously been created with
|
||||||
* registered with rtnetlink_link_notifier_register(). */
|
* rtnetlink_link_notifier_register(). */
|
||||||
void
|
void
|
||||||
rtnetlink_link_notifier_unregister(struct nln_notifier *notifier)
|
rtnetlink_link_notifier_destroy(struct nln_notifier *notifier)
|
||||||
{
|
{
|
||||||
nln_notifier_unregister(nln, notifier);
|
nln_notifier_destroy(notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calls all of the registered notifiers, passing along any as-yet-unreported
|
/* Calls all of the registered notifiers, passing along any as-yet-unreported
|
||||||
|
@@ -50,9 +50,9 @@ void rtnetlink_link_notify_func(const struct rtnetlink_link_change *change,
|
|||||||
|
|
||||||
bool rtnetlink_link_parse(struct ofpbuf *buf,
|
bool rtnetlink_link_parse(struct ofpbuf *buf,
|
||||||
struct rtnetlink_link_change *change);
|
struct rtnetlink_link_change *change);
|
||||||
int rtnetlink_link_notifier_register(struct nln_notifier*,
|
struct nln_notifier *
|
||||||
rtnetlink_link_notify_func *, void *aux);
|
rtnetlink_link_notifier_create(rtnetlink_link_notify_func *, void *aux);
|
||||||
void rtnetlink_link_notifier_unregister(struct nln_notifier *);
|
void rtnetlink_link_notifier_destroy(struct nln_notifier *);
|
||||||
void rtnetlink_link_run(void);
|
void rtnetlink_link_run(void);
|
||||||
void rtnetlink_link_wait(void);
|
void rtnetlink_link_wait(void);
|
||||||
#endif /* rtnetlink-link.h */
|
#endif /* rtnetlink-link.h */
|
||||||
|
@@ -799,7 +799,7 @@ int
|
|||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
extern struct vlog_module VLM_reconnect;
|
extern struct vlog_module VLM_reconnect;
|
||||||
struct nln_notifier link_notifier;
|
struct nln_notifier *link_notifier;
|
||||||
struct unixctl_server *unixctl;
|
struct unixctl_server *unixctl;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@@ -823,8 +823,7 @@ main(int argc, char *argv[])
|
|||||||
"\"brcompat\" kernel module.");
|
"\"brcompat\" kernel module.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
link_notifier = rtnetlink_link_notifier_create(netdev_changed_cb, NULL);
|
||||||
rtnetlink_link_notifier_register(&link_notifier, netdev_changed_cb, NULL);
|
|
||||||
|
|
||||||
daemonize_complete();
|
daemonize_complete();
|
||||||
|
|
||||||
@@ -842,7 +841,7 @@ main(int argc, char *argv[])
|
|||||||
poll_block();
|
poll_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
rtnetlink_link_notifier_unregister(&link_notifier);
|
rtnetlink_link_notifier_destroy(link_notifier);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user