X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Frtnetlink.c;h=b600554390ee162d1b0d67e8f4d1dc8ddb76caa9;hb=3a48ace3e4799ce25099a8584372abe7a4d6d771;hp=5d80d7258fa3ea2009f00e11391d4f4821e050e0;hpb=21d6e22eeec05a1c382178dc2eb840afe3b9cca6;p=openvswitch diff --git a/lib/rtnetlink.c b/lib/rtnetlink.c index 5d80d725..b6005543 100644 --- a/lib/rtnetlink.c +++ b/lib/rtnetlink.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010 Nicira Networks. + * Copyright (c) 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ #include #include +#include #include "coverage.h" #include "netlink.h" @@ -36,6 +37,7 @@ static void rtnetlink_report(struct rtnetlink *rtn, void *change); 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. */ @@ -54,15 +56,27 @@ rtnetlink_create(int multicast_group, rtnetlink_parse_func *parse, 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; } +/* Destroys 'rtn' by freeing any memory it has reserved and closing any sockets + * it has opened. */ +void +rtnetlink_destroy(struct rtnetlink *rtn) +{ + if (rtn) { + nl_sock_destroy(rtn->notify_sock); + free(rtn); + } +} + /* Registers 'cb' to be called with auxiliary data 'aux' with change * notifications. The notifier is stored in 'notifier', which the caller must * not modify or free. @@ -77,13 +91,20 @@ rtnetlink_notifier_register(struct rtnetlink *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. */ @@ -116,10 +137,11 @@ rtnetlink_notifier_run(struct rtnetlink *rtn) { 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; @@ -151,6 +173,7 @@ rtnetlink_notifier_run(struct rtnetlink *rtn) void rtnetlink_notifier_wait(struct rtnetlink *rtn) { + rtn->has_run = false; if (rtn->notify_sock) { nl_sock_wait(rtn->notify_sock, POLLIN); }