struct rtnetlink {
struct nl_sock *notify_sock; /* Rtnetlink socket. */
struct list all_notifiers; /* All rtnetlink notifiers. */
+ bool has_run; /* Guard for run and wait functions. */
/* Passed in by rtnetlink_create(). */
int multicast_group; /* Multicast group we listen on. */
struct rtnetlink *rtn;
rtn = xzalloc(sizeof *rtn);
- rtn->notify_sock = 0;
+ rtn->notify_sock = NULL;
rtn->multicast_group = multicast_group;
rtn->parse = parse;
rtn->change = change;
+ rtn->has_run = false;
list_init(&rtn->all_notifiers);
return rtn;
rtnetlink_notify_func *cb, void *aux)
{
if (!rtn->notify_sock) {
- int error = nl_sock_create(NETLINK_ROUTE, rtn->multicast_group, 0, 0,
- &rtn->notify_sock);
+ struct nl_sock *sock;
+ int error;
+
+ error = nl_sock_create(NETLINK_ROUTE, &sock);
+ if (!error) {
+ error = nl_sock_join_mcgroup(sock, rtn->multicast_group);
+ }
if (error) {
+ nl_sock_destroy(sock);
VLOG_WARN("could not create rtnetlink socket: %s",
strerror(error));
return error;
}
+ rtn->notify_sock = sock;
} else {
/* Catch up on notification work so that the new notifier won't
* receive any stale notifications. */
{
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
- if (!rtn->notify_sock) {
+ if (!rtn->notify_sock || rtn->has_run) {
return;
}
+ rtn->has_run = true;
for (;;) {
struct ofpbuf *buf;
int error;
void
rtnetlink_notifier_wait(struct rtnetlink *rtn)
{
+ rtn->has_run = false;
if (rtn->notify_sock) {
nl_sock_wait(rtn->notify_sock, POLLIN);
}