* Fix:
+ Better compliance for statsTLVsUnrecognizedTotal and
statsAgeoutsTotal counters.
+ + On Linux, handle rare blocking case in Netlink code.
lldpd (1.0.3)
* Fix:
}
return 0;
}
+
+#ifdef HOST_OS_LINUX
+/* Receive and log error from a socket when there is suspicion of an error. */
+void
+levent_recv_error(int fd, const char *source)
+{
+ do {
+ ssize_t n;
+ char buf[1024] = {};
+ struct msghdr msg = {
+ .msg_control = buf,
+ .msg_controllen = sizeof(buf)
+ };
+ if ((n = recvmsg(fd, &msg, MSG_ERRQUEUE | MSG_DONTWAIT)) <= 0) {
+ return;
+ }
+ struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+ if (cmsg == NULL)
+ log_warnx("event", "received unknown error on %s",
+ source);
+ else
+ log_warnx("event", "received error (level=%d/type=%d) on %s",
+ cmsg->cmsg_level, cmsg->cmsg_type, source);
+ } while (1);
+}
+#endif
buffer, size);
}
-static void
-iflinux_error_recv(struct lldpd_hardware *hardware, int fd)
-{
- do {
- ssize_t n;
- char buf[1024] = {};
- struct msghdr msg = {
- .msg_control = buf,
- .msg_controllen = sizeof(buf)
- };
- if ((n = recvmsg(fd, &msg, MSG_ERRQUEUE)) <= 0) {
- return;
- }
- struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
- if (cmsg == NULL)
- log_warnx("interfaces", "received unknown error on %s",
- hardware->h_ifname);
- else
- log_warnx("interfaces", "received error (level=%d/type=%d) on %s",
- cmsg->cmsg_level, cmsg->cmsg_type, hardware->h_ifname);
- } while (1);
-}
-
static int
iflinux_generic_recv(struct lldpd_hardware *hardware,
int fd, char *buffer, size_t size,
&fromlen)) == -1) {
if (errno == EAGAIN && retry == 0) {
/* There may be an error queued in the socket. Clear it and retry. */
- iflinux_error_recv(hardware, fd);
+ levent_recv_error(fd, hardware->h_ifname);
retry++;
goto retry;
}
void levent_schedule_cleanup(struct lldpd *);
int levent_make_socket_nonblocking(int);
int levent_make_socket_blocking(int);
+#ifdef HOST_OS_LINUX
+void levent_recv_error(int, const char*);
+#endif
/* lldp.c */
int lldp_send_shutdown(PROTO_SEND_SIG);
struct interfaces_device_list *ifs,
struct interfaces_address_list *ifas)
{
- int end = 0, ret = 0;
- int flags = MSG_PEEK | MSG_TRUNC;
+ int end = 0, ret = 0, flags, retry = 0;
struct iovec iov;
int link_update = 0;
int s = cfg->g_netlink->nl_socket;
.msg_name = &peer,
.msg_namelen = sizeof(struct sockaddr_nl)
};
-
+ flags = MSG_PEEK | MSG_TRUNC;
retry:
- len = recvmsg(s, &rtnl_reply, flags);
+ len = recvmsg(s, &rtnl_reply, flags | MSG_DONTWAIT);
if (len == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
- log_debug("netlink", "should have received something, but didn't");
+ if (retry++ == 0) {
+ levent_recv_error(s, "netlink socket");
+ goto retry;
+ }
+ log_warnx("netlink", "should have received something, but didn't");
ret = 0;
goto out;
}
msg->nlmsg_type, msg->nlmsg_len);
}
}
- flags = MSG_PEEK | MSG_TRUNC;
}
end:
if (link_update) {