Merge "master" into "next".
[cascardo/ovs.git] / utilities / nlmon.c
1 /*
2  * Copyright (c) 2009, 2010 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <net/if.h>
21 #include <poll.h>
22 #include <sys/socket.h>
23 #include <sys/uio.h>
24 #include <stddef.h>
25 #include <linux/rtnetlink.h>
26 #include "netlink.h"
27 #include "ofpbuf.h"
28 #include "poll-loop.h"
29 #include "timeval.h"
30 #include "util.h"
31 #include "vlog.h"
32
33 static const struct nl_policy rtnlgrp_link_policy[] = {
34     [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
35     [IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
36 };
37
38 int
39 main(int argc OVS_UNUSED, char *argv[])
40 {
41     struct nl_sock *sock;
42     int error;
43
44     set_program_name(argv[0]);
45     time_init();
46     vlog_init();
47     vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
48
49     error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
50     if (error) {
51         ovs_fatal(error, "could not create rtnetlink socket");
52     }
53
54     for (;;) {
55         struct ofpbuf *buf;
56
57         error = nl_sock_recv(sock, &buf, false);
58         if (error == EAGAIN) {
59             /* Nothing to do. */
60         } else if (error == ENOBUFS) {
61             ovs_error(0, "network monitor socket overflowed");
62         } else if (error) {
63             ovs_fatal(error, "error on network monitor socket");
64         } else {
65             struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)];
66             struct nlmsghdr *nlh;
67             struct ifinfomsg *iim;
68
69             nlh = ofpbuf_at(buf, 0, NLMSG_HDRLEN);
70             iim = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *iim);
71             if (!iim) {
72                 ovs_error(0, "received bad rtnl message (no ifinfomsg)");
73                 ofpbuf_delete(buf);
74                 continue;
75             }
76
77             if (!nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
78                                  rtnlgrp_link_policy,
79                                  attrs, ARRAY_SIZE(rtnlgrp_link_policy))) {
80                 ovs_error(0, "received bad rtnl message (policy)");
81                 ofpbuf_delete(buf);
82                 continue;
83             }
84             printf("netdev %s changed (%s):\n",
85                    nl_attr_get_string(attrs[IFLA_IFNAME]),
86                    (nlh->nlmsg_type == RTM_NEWLINK ? "RTM_NEWLINK"
87                     : nlh->nlmsg_type == RTM_DELLINK ? "RTM_DELLINK"
88                     : nlh->nlmsg_type == RTM_GETLINK ? "RTM_GETLINK"
89                     : nlh->nlmsg_type == RTM_SETLINK ? "RTM_SETLINK"
90                     : "other"));
91             if (attrs[IFLA_MASTER]) {
92                 uint32_t idx = nl_attr_get_u32(attrs[IFLA_MASTER]);
93                 char ifname[IFNAMSIZ];
94                 if (!if_indextoname(idx, ifname)) {
95                     strcpy(ifname, "unknown");
96                 }
97                 printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname);
98             }
99             ofpbuf_delete(buf);
100         }
101
102         nl_sock_wait(sock, POLLIN);
103         poll_block();
104     }
105 }
106