eb1be60a71394c2dbccb2baea31d2dd3e375862b
[cascardo/ovs.git] / utilities / nlmon.c
1 #include <config.h>
2 #include <errno.h>
3 #include <inttypes.h>
4 #include <net/if.h>
5 #include <poll.h>
6 #include <sys/socket.h>
7 #include <sys/uio.h>
8 #include <stddef.h>
9 #include <linux/rtnetlink.h>
10 #include "netlink.h"
11 #include "ofpbuf.h"
12 #include "poll-loop.h"
13 #include "timeval.h"
14 #include "util.h"
15 #include "vlog.h"
16
17 static const struct nl_policy rtnlgrp_link_policy[] = {
18     [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
19     [IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
20 };
21
22 int
23 main(int argc UNUSED, char *argv[])
24 {
25     struct nl_sock *sock;
26     int error;
27
28     set_program_name(argv[0]);
29     time_init();
30     vlog_init();
31     vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
32
33     error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
34     if (error) {
35         ovs_fatal(error, "could not create rtnetlink socket");
36     }
37
38     for (;;) {
39         struct ofpbuf *buf;
40
41         error = nl_sock_recv(sock, &buf, false);
42         if (error == EAGAIN) {
43             /* Nothing to do. */
44         } else if (error == ENOBUFS) {
45             ovs_error(0, "network monitor socket overflowed");
46         } else if (error) {
47             ovs_fatal(error, "error on network monitor socket");
48         } else {
49             struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)];
50             struct nlmsghdr *nlh;
51             struct ifinfomsg *iim;
52
53             nlh = ofpbuf_at(buf, 0, NLMSG_HDRLEN);
54             iim = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *iim);
55             if (!iim) {
56                 ovs_error(0, "received bad rtnl message (no ifinfomsg)");
57                 ofpbuf_delete(buf);
58                 continue;
59             }
60
61             if (!nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
62                                  rtnlgrp_link_policy,
63                                  attrs, ARRAY_SIZE(rtnlgrp_link_policy))) {
64                 ovs_error(0, "received bad rtnl message (policy)");
65                 ofpbuf_delete(buf);
66                 continue;
67             }
68             printf("netdev %s changed (%s):\n",
69                    nl_attr_get_string(attrs[IFLA_IFNAME]),
70                    (nlh->nlmsg_type == RTM_NEWLINK ? "RTM_NEWLINK"
71                     : nlh->nlmsg_type == RTM_DELLINK ? "RTM_DELLINK"
72                     : nlh->nlmsg_type == RTM_GETLINK ? "RTM_GETLINK"
73                     : nlh->nlmsg_type == RTM_SETLINK ? "RTM_SETLINK"
74                     : "other"));
75             if (attrs[IFLA_MASTER]) {
76                 uint32_t idx = nl_attr_get_u32(attrs[IFLA_MASTER]);
77                 char ifname[IFNAMSIZ];
78                 if (!if_indextoname(idx, ifname)) {
79                     strcpy(ifname, "unknown");
80                 }
81                 printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname);
82             }
83             ofpbuf_delete(buf);
84         }
85
86         nl_sock_wait(sock, POLLIN);
87         poll_block();
88     }
89 }
90