Attempt to recover from transient network errors

This commit is contained in:
Jeremy Lakeman 2015-11-23 09:47:45 +10:30
parent bdb3b99143
commit fd38ddb892

View File

@ -59,6 +59,7 @@ struct profile_total sock_any_stats;
static void overlay_interface_poll(struct sched_ent *alarm); static void overlay_interface_poll(struct sched_ent *alarm);
static int inet_up_count=0; static int inet_up_count=0;
static void rescan_soon();
void overlay_interface_close(overlay_interface *interface) void overlay_interface_close(overlay_interface *interface)
{ {
@ -1058,18 +1059,23 @@ int overlay_broadcast_ensemble(struct network_destination *destination, struct o
bytes, (size_t)len, 0, bytes, (size_t)len, 0,
&destination->address.addr, destination->address.addrlen); &destination->address.addr, destination->address.addrlen);
if (sent == -1){ if (sent == -1){
if (errno!=EAGAIN && errno!=EWOULDBLOCK && errno!=ENOENT && errno!=ENOTDIR) if (errno!=EAGAIN && errno!=EWOULDBLOCK && errno!=ENOENT && errno!=ENOTDIR){
WHYF_perror("sendto(fd=%d,len=%zu,addr=%s) on interface %s", WHYF_perror("sendto(fd=%d,len=%zu,addr=%s) on interface %s",
interface->alarm.poll.fd, interface->alarm.poll.fd,
(size_t)len, (size_t)len,
alloca_socket_address(&destination->address), alloca_socket_address(&destination->address),
interface->name interface->name
); );
// close the interface if we had any error while sending broadcast packets,
// unicast packets should not bring the interface down // if we had any error while sending broadcast packets,
// TODO mark unicast destination as failed? // it could be because the interface is coming down
if (destination == interface->destination) // or there might be some socket error that we can't fix.
// So bring the interface down, and scan for network changes soon
if (destination == interface->destination){
overlay_interface_close(interface); overlay_interface_close(interface);
rescan_soon();
}
}
ob_free(buffer); ob_free(buffer);
return -1; return -1;
} }
@ -1279,7 +1285,7 @@ static int netlink_socket()
return sock; return sock;
} }
static int netlink_send_get(int fd) static int netlink_send_get()
{ {
struct { struct {
struct nlmsghdr n; struct nlmsghdr n;
@ -1294,6 +1300,7 @@ static int netlink_send_get(int fd)
struct rtattr *rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len)); struct rtattr *rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
rta->rta_len = RTA_LENGTH(4); rta->rta_len = RTA_LENGTH(4);
int fd = ALARM_STRUCT(netlink_poll).poll.fd;
if (send(fd, &req, req.n.nlmsg_len, 0)<0) if (send(fd, &req, req.n.nlmsg_len, 0)<0)
return WHYF_perror("send(%d)", fd); return WHYF_perror("send(%d)", fd);
@ -1315,7 +1322,7 @@ static int netlink_init()
watch(alarm); watch(alarm);
} }
return netlink_send_get(alarm->poll.fd); return 0;
} }
#else #else
@ -1406,6 +1413,18 @@ static void file_interface_init(const struct config_network_interface *ifconfig)
overlay_interface_init(ifconfig->file, &addr, &netmask, &broadcast, ifconfig); overlay_interface_init(ifconfig->file, &addr, &netmask, &broadcast, ifconfig);
} }
static void rescan_soon(){
#ifdef HAVE_LINUX_NETLINK_H
// start listening for network changes & request current interface addresses
netlink_init();
netlink_send_get();
#else
// re-check all interfaces periodically
time_ms_t now = gettime_ms();
RESCHEDULE(&ALARM_STRUCT(overlay_interface_discover), now, now, now);
#endif
}
void overlay_interface_config_change() void overlay_interface_config_change()
{ {
unsigned i; unsigned i;
@ -1449,16 +1468,8 @@ void overlay_interface_config_change()
file_interface_init(ifconfig); file_interface_init(ifconfig);
} }
if (real_interface){ if (real_interface)
#ifdef HAVE_LINUX_NETLINK_H rescan_soon();
// start listening for network changes & request current interface addresses
netlink_init();
#else
// re-check all interfaces periodically
time_ms_t now = gettime_ms();
RESCHEDULE(&ALARM_STRUCT(overlay_interface_discover), now, now, now);
#endif
}
} }
void logServalPacket(int level, struct __sourceloc __whence, const char *message, const unsigned char *packet, size_t len) { void logServalPacket(int level, struct __sourceloc __whence, const char *message, const unsigned char *packet, size_t len) {