summaryrefslogtreecommitdiff
path: root/utilities/nlmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'utilities/nlmon.c')
-rw-r--r--utilities/nlmon.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/utilities/nlmon.c b/utilities/nlmon.c
new file mode 100644
index 000000000..eb1be60a7
--- /dev/null
+++ b/utilities/nlmon.c
@@ -0,0 +1,90 @@
+#include <config.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <net/if.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <stddef.h>
+#include <linux/rtnetlink.h>
+#include "netlink.h"
+#include "ofpbuf.h"
+#include "poll-loop.h"
+#include "timeval.h"
+#include "util.h"
+#include "vlog.h"
+
+static const struct nl_policy rtnlgrp_link_policy[] = {
+ [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
+ [IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
+};
+
+int
+main(int argc UNUSED, char *argv[])
+{
+ struct nl_sock *sock;
+ int error;
+
+ set_program_name(argv[0]);
+ time_init();
+ vlog_init();
+ vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+
+ error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
+ if (error) {
+ ovs_fatal(error, "could not create rtnetlink socket");
+ }
+
+ for (;;) {
+ struct ofpbuf *buf;
+
+ error = nl_sock_recv(sock, &buf, false);
+ if (error == EAGAIN) {
+ /* Nothing to do. */
+ } else if (error == ENOBUFS) {
+ ovs_error(0, "network monitor socket overflowed");
+ } else if (error) {
+ ovs_fatal(error, "error on network monitor socket");
+ } else {
+ struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)];
+ struct nlmsghdr *nlh;
+ struct ifinfomsg *iim;
+
+ nlh = ofpbuf_at(buf, 0, NLMSG_HDRLEN);
+ iim = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *iim);
+ if (!iim) {
+ ovs_error(0, "received bad rtnl message (no ifinfomsg)");
+ ofpbuf_delete(buf);
+ continue;
+ }
+
+ if (!nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
+ rtnlgrp_link_policy,
+ attrs, ARRAY_SIZE(rtnlgrp_link_policy))) {
+ ovs_error(0, "received bad rtnl message (policy)");
+ ofpbuf_delete(buf);
+ continue;
+ }
+ printf("netdev %s changed (%s):\n",
+ nl_attr_get_string(attrs[IFLA_IFNAME]),
+ (nlh->nlmsg_type == RTM_NEWLINK ? "RTM_NEWLINK"
+ : nlh->nlmsg_type == RTM_DELLINK ? "RTM_DELLINK"
+ : nlh->nlmsg_type == RTM_GETLINK ? "RTM_GETLINK"
+ : nlh->nlmsg_type == RTM_SETLINK ? "RTM_SETLINK"
+ : "other"));
+ if (attrs[IFLA_MASTER]) {
+ uint32_t idx = nl_attr_get_u32(attrs[IFLA_MASTER]);
+ char ifname[IFNAMSIZ];
+ if (!if_indextoname(idx, ifname)) {
+ strcpy(ifname, "unknown");
+ }
+ printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname);
+ }
+ ofpbuf_delete(buf);
+ }
+
+ nl_sock_wait(sock, POLLIN);
+ poll_block();
+ }
+}
+