vlog: Avoid calling worker_request() reentrantly.
[sliver-openvswitch.git] / utilities / nlmon.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
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 "netlink-socket.h"
28 #include "ofpbuf.h"
29 #include "poll-loop.h"
30 #include "timeval.h"
31 #include "util.h"
32 #include "vlog.h"
33
34 static const struct nl_policy rtnlgrp_link_policy[] = {
35     [IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
36     [IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
37 };
38
39 int
40 main(int argc OVS_UNUSED, char *argv[])
41 {
42     uint64_t buf_stub[4096 / 64];
43     struct nl_sock *sock;
44     struct ofpbuf buf;
45     int error;
46
47     set_program_name(argv[0]);
48     vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
49
50     error = nl_sock_create(NETLINK_ROUTE, &sock);
51     if (error) {
52         ovs_fatal(error, "could not create rtnetlink socket");
53     }
54
55     error = nl_sock_join_mcgroup(sock, RTNLGRP_LINK);
56     if (error) {
57         ovs_fatal(error, "could not join RTNLGRP_LINK multicast group");
58     }
59
60     ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub);
61     for (;;) {
62         error = nl_sock_recv(sock, &buf, false);
63         if (error == EAGAIN) {
64             /* Nothing to do. */
65         } else if (error == ENOBUFS) {
66             ovs_error(0, "network monitor socket overflowed");
67         } else if (error) {
68             ovs_fatal(error, "error on network monitor socket");
69         } else {
70             struct iff_flag {
71                 unsigned int flag;
72                 const char *name;
73             };
74
75             static const struct iff_flag flags[] = {
76                 { IFF_UP, "UP", },
77                 { IFF_BROADCAST, "BROADCAST", },
78                 { IFF_DEBUG, "DEBUG", },
79                 { IFF_LOOPBACK, "LOOPBACK", },
80                 { IFF_POINTOPOINT, "POINTOPOINT", },
81                 { IFF_NOTRAILERS, "NOTRAILERS", },
82                 { IFF_RUNNING, "RUNNING", },
83                 { IFF_NOARP, "NOARP", },
84                 { IFF_PROMISC, "PROMISC", },
85                 { IFF_ALLMULTI, "ALLMULTI", },
86                 { IFF_MASTER, "MASTER", },
87                 { IFF_SLAVE, "SLAVE", },
88                 { IFF_MULTICAST, "MULTICAST", },
89                 { IFF_PORTSEL, "PORTSEL", },
90                 { IFF_AUTOMEDIA, "AUTOMEDIA", },
91                 { IFF_DYNAMIC, "DYNAMIC", },
92             };
93
94             struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)];
95             struct nlmsghdr *nlh;
96             struct ifinfomsg *iim;
97             int i;
98
99             nlh = ofpbuf_at(&buf, 0, NLMSG_HDRLEN);
100             iim = ofpbuf_at(&buf, NLMSG_HDRLEN, sizeof *iim);
101             if (!iim) {
102                 ovs_error(0, "received bad rtnl message (no ifinfomsg)");
103                 continue;
104             }
105
106             if (!nl_policy_parse(&buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg),
107                                  rtnlgrp_link_policy,
108                                  attrs, ARRAY_SIZE(rtnlgrp_link_policy))) {
109                 ovs_error(0, "received bad rtnl message (policy)");
110                 continue;
111             }
112             printf("netdev %s changed (%s):\n",
113                    nl_attr_get_string(attrs[IFLA_IFNAME]),
114                    (nlh->nlmsg_type == RTM_NEWLINK ? "RTM_NEWLINK"
115                     : nlh->nlmsg_type == RTM_DELLINK ? "RTM_DELLINK"
116                     : nlh->nlmsg_type == RTM_GETLINK ? "RTM_GETLINK"
117                     : nlh->nlmsg_type == RTM_SETLINK ? "RTM_SETLINK"
118                     : "other"));
119             printf("\tflags:");
120             for (i = 0; i < ARRAY_SIZE(flags); i++) {
121                 if (iim->ifi_flags & flags[i].flag) {
122                     printf(" %s", flags[i].name);
123                 }
124             }
125             printf("\n");
126             if (attrs[IFLA_MASTER]) {
127                 uint32_t idx = nl_attr_get_u32(attrs[IFLA_MASTER]);
128                 char ifname[IFNAMSIZ];
129                 if (!if_indextoname(idx, ifname)) {
130                     strcpy(ifname, "unknown");
131                 }
132                 printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname);
133             }
134         }
135
136         nl_sock_wait(sock, POLLIN);
137         poll_block();
138     }
139 }
140