From 43673d4bfc21352c7d93fc4ceee864b59fc11a71 Mon Sep 17 00:00:00 2001 From: Rui Paulo Date: Wed, 7 Aug 2013 01:01:58 +0000 Subject: [PATCH] Fix a timing issue with the wired driver. After configuring the interface, wait for the link to become active. Many ethernet drivers reset the chip when we set multicast filters (causing significant delays due to link re-negotiation) and, by the time we start sending packets, they are discared instead of going to the ether. Tested by: dumbbell --- contrib/wpa/src/drivers/driver_wired.c | 31 +++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/contrib/wpa/src/drivers/driver_wired.c b/contrib/wpa/src/drivers/driver_wired.c index e0f0f2289bc..95dcea9354a 100644 --- a/contrib/wpa/src/drivers/driver_wired.c +++ b/contrib/wpa/src/drivers/driver_wired.c @@ -17,6 +17,7 @@ #endif /* __linux__ */ #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) #include +#include #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */ #ifdef __sun__ #include @@ -453,6 +454,29 @@ static int wpa_driver_wired_set_ifflags(const char *ifname, int flags) return 0; } +static int wpa_driver_wired_get_ifstatus(const char *ifname, int *status) +{ + struct ifmediareq ifmr; + int s; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) { + perror("socket"); + return -1; + } + + os_memset(&ifmr, 0, sizeof(ifmr)); + os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ); + if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) { + perror("ioctl[SIOCGIFMEDIA]"); + close(s); + return -1; + } + close(s); + *status = ifmr.ifm_status & IFM_ACTIVE; + + return 0; +} static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add) { @@ -511,7 +535,7 @@ static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add) static void * wpa_driver_wired_init(void *ctx, const char *ifname) { struct wpa_driver_wired_data *drv; - int flags; + int flags, status; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) @@ -562,6 +586,11 @@ static void * wpa_driver_wired_init(void *ctx, const char *ifname) __func__); drv->iff_allmulti = 1; } + wpa_printf(MSG_DEBUG, "%s: waiting for link to become active", + __func__); + while (wpa_driver_wired_get_ifstatus(ifname, &status) == 0 && + status == 0) + sleep(1); return drv; }