Hi Felix, Regarding the resubmitted netifd linksensing patches (which solve the original issue reported in https://dev.openwrt.org/ticket/14590) did you have some time to review them ? I noticed two other netifd patches were applied from the same patch series but none of the linksensing and bridge mtu patches.
Thx, Hans On Tue, Feb 11, 2014 at 10:30 AM, Hans Dedecker <dedec...@gmail.com> wrote: > Device layer is informed by netlink events regarding the link layer > status. Link > layer status change results in a DEV_EVENT_LINK_UP/DEV_EVENT_LINK_DOWN > broadcast > event for a given device. > > Depends on uloop error callback patch. > > Solves issue reported in https://dev.openwrt.org/ticket/14590 > > Signed-off-by: Hans Dedecker <dedec...@gmail.com> > Acked-by: Karl Vogel <karl.vo...@gmail.com> > --- > device.c | 29 ++++++++++- > device.h | 4 ++ > system-linux.c | 154 > +++++++++++++++++++++++++++++++++++++++++++++++-------- > 3 files changed, 162 insertions(+), 25 deletions(-) > > diff --git a/device.c b/device.c > index feeb290..6a770ac 100644 > --- a/device.c > +++ b/device.c > @@ -211,7 +211,7 @@ int device_claim(struct device_user *dep) > return 0; > > dep->claimed = true; > - D(DEVICE, "Claim %s %s, new refcount: %d\n", dev->type->name, > dev->ifname, dev->active + 1); > + D(DEVICE, "Claim %s %s, new active count: %d\n", dev->type->name, > dev->ifname, dev->active + 1); > if (++dev->active != 1) > return 0; > > @@ -237,7 +237,7 @@ void device_release(struct device_user *dep) > > dep->claimed = false; > dev->active--; > - D(DEVICE, "Release %s %s, new refcount: %d\n", dev->type->name, > dev->ifname, dev->active); > + D(DEVICE, "Release %s %s, new active count: %d\n", > dev->type->name, dev->ifname, dev->active); > assert(dev->active >= 0); > > if (dev->active) > @@ -394,6 +394,26 @@ void device_set_present(struct device *dev, bool > state) > device_refresh_present(dev); > } > > +void device_set_link(struct device *dev, bool state) > +{ > + if (dev->link_active == state) > + return; > + > + netifd_log_message(L_NOTICE, "%s '%s' link is %s\n", > dev->type->name, dev->ifname, state ? "up" : "down" ); > + > + dev->link_active = state; > + device_broadcast_event(dev, state ? DEV_EVENT_LINK_UP : > DEV_EVENT_LINK_DOWN); > +} > + > +void device_set_ifindex(struct device *dev, int ifindex) > +{ > + if (dev->ifindex == ifindex) > + return; > + > + dev->ifindex = ifindex; > + device_broadcast_event(dev, DEV_EVENT_UPDATE_IFINDEX); > +} > + > static int device_refcount(struct device *dev) > { > struct list_head *list; > @@ -435,6 +455,9 @@ void device_add_user(struct device_user *dep, struct > device *dev) > dep->cb(dep, DEV_EVENT_ADD); > if (dev->active) > dep->cb(dep, DEV_EVENT_UP); > + > + if (dev->link_active) > + dep->cb(dep, DEV_EVENT_LINK_UP); > } > } > > @@ -667,6 +690,8 @@ device_dump_status(struct blob_buf *b, struct device > *dev) > return; > > blobmsg_add_u8(b, "up", !!dev->active); > + blobmsg_add_u8(b, "carrier", !!dev->link_active); > + > if (dev->type->dump_info) > dev->type->dump_info(dev, b); > else > diff --git a/device.h b/device.h > index d63ffe3..dd57927 100644 > --- a/device.h > +++ b/device.h > @@ -68,6 +68,7 @@ enum device_event { > DEV_EVENT_REMOVE, > > DEV_EVENT_UPDATE_IFNAME, > + DEV_EVENT_UPDATE_IFINDEX, > > DEV_EVENT_SETUP, > DEV_EVENT_TEARDOWN, > @@ -122,6 +123,7 @@ struct device { > bool sys_present; > bool present; > int active; > + bool link_active; > > bool external; > bool disabled; > @@ -178,6 +180,8 @@ void device_remove_user(struct device_user *dep); > void device_broadcast_event(struct device *dev, enum device_event ev); > > void device_set_present(struct device *dev, bool state); > +void device_set_link(struct device *dev, bool state); > +void device_set_ifindex(struct device *dev, int ifindex); > void device_refresh_present(struct device *dev); > int device_claim(struct device_user *dep); > void device_release(struct device_user *dep); > diff --git a/system-linux.c b/system-linux.c > index e1b9924..f0cea34 100644 > --- a/system-linux.c > +++ b/system-linux.c > @@ -58,7 +58,7 @@ > struct event_socket { > struct uloop_fd uloop; > struct nl_sock *sock; > - struct nl_cb *cb; > + int bufsize; > }; > > static int sock_ioctl = -1; > @@ -73,7 +73,38 @@ static void > handler_nl_event(struct uloop_fd *u, unsigned int events) > { > struct event_socket *ev = container_of(u, struct event_socket, > uloop); > - nl_recvmsgs(ev->sock, ev->cb); > + int err; > + socklen_t errlen = sizeof(err); > + > + if (!u->error) { > + nl_recvmsgs_default(ev->sock); > + return; > + } > + > + if (getsockopt(u->fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen)) > + goto abort; > + > + switch(err) { > + case ENOBUFS: > + // Increase rx buffer size on netlink socket > + ev->bufsize *= 2; > + if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0)) > + goto abort; > + > + // Request full dump since some info got dropped > + struct rtgenmsg msg = { .rtgen_family = AF_UNSPEC }; > + nl_send_simple(ev->sock, RTM_GETLINK, NLM_F_DUMP, &msg, > sizeof(msg)); > + break; > + > + default: > + goto abort; > + } > + u->error = false; > + return; > + > +abort: > + uloop_fd_delete(&ev->uloop); > + return; > } > > static struct nl_sock * > @@ -96,7 +127,7 @@ create_socket(int protocol, int groups) > > static bool > create_raw_event_socket(struct event_socket *ev, int protocol, int groups, > - uloop_fd_handler cb) > + uloop_fd_handler cb, int flags) > { > ev->sock = create_socket(protocol, groups); > if (!ev->sock) > @@ -104,7 +135,9 @@ create_raw_event_socket(struct event_socket *ev, int > protocol, int groups, > > ev->uloop.fd = nl_socket_get_fd(ev->sock); > ev->uloop.cb = cb; > - uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER); > + if (uloop_fd_add(&ev->uloop, ULOOP_READ|flags)) > + return false; > + > return true; > } > > @@ -112,14 +145,21 @@ static bool > create_event_socket(struct event_socket *ev, int protocol, > int (*cb)(struct nl_msg *msg, void *arg)) > { > - // Prepare socket for link events > - ev->cb = nl_cb_alloc(NL_CB_DEFAULT); > - if (!ev->cb) > + if (!create_raw_event_socket(ev, protocol, 0, handler_nl_event, > ULOOP_ERROR_CB)) > return false; > > - nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL); > + // Install the valid custom callback handler > + nl_socket_modify_cb(ev->sock, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL); > + > + // Disable sequence number checking on event sockets > + nl_socket_disable_seq_check(ev->sock); > > - return create_raw_event_socket(ev, protocol, 0, handler_nl_event); > + // Increase rx buffer size to 65K on event sockets > + ev->bufsize = 65535; > + if (nl_socket_set_buffer_size(ev->sock, ev->bufsize, 0)) > + return false; > + > + return true; > } > > int system_init(void) > @@ -128,7 +168,7 @@ int system_init(void) > static struct event_socket hotplug_event; > > sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0); > - fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | > FD_CLOEXEC); > + system_fd_set_cloexec(sock_ioctl); > > // Prepare socket for routing / address control > sock_rtnl = create_socket(NETLINK_ROUTE, 0); > @@ -139,7 +179,7 @@ int system_init(void) > return -1; > > if (!create_raw_event_socket(&hotplug_event, > NETLINK_KOBJECT_UEVENT, 1, > - handle_hotplug_event)) > + handle_hotplug_event, 0)) > return -1; > > // Receive network link events form kernel > @@ -171,6 +211,10 @@ static void system_set_disable_ipv6(struct device > *dev, const char *val) > system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", > dev->ifname, val); > } > > +#ifndef IFF_LOWER_UP > +#define IFF_LOWER_UP 0x10000 > +#endif > + > // Evaluate netlink messages > static int cb_rtnl_event(struct nl_msg *msg, void *arg) > { > @@ -178,19 +222,19 @@ static int cb_rtnl_event(struct nl_msg *msg, void > *arg) > struct ifinfomsg *ifi = NLMSG_DATA(nh); > struct nlattr *nla[__IFLA_MAX]; > > - if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK) > + if (nh->nlmsg_type != RTM_NEWLINK) > goto out; > > nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL); > if (!nla[IFLA_IFNAME]) > goto out; > > - struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false); > + struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false); > if (!dev) > goto out; > > - dev->ifindex = ifi->ifi_index; > - /* TODO: parse link status */ > + device_set_ifindex(dev, ifi->ifi_index); > + device_set_link(dev, ifi->ifi_flags & IFF_LOWER_UP ? true : false); > > out: > return 0; > @@ -538,7 +582,7 @@ void system_if_clear_state(struct device *dev) > if (dev->external) > return; > > - dev->ifindex = system_if_resolve(dev); > + device_set_ifindex(dev, system_if_resolve(dev)); > if (!dev->ifindex) > return; > > @@ -782,7 +826,7 @@ int system_if_up(struct device *dev) > { > system_if_get_settings(dev, &dev->orig_settings); > system_if_apply_settings(dev, &dev->settings); > - dev->ifindex = system_if_resolve(dev); > + device_set_ifindex(dev, system_if_resolve(dev)); > return system_if_flags(dev->ifname, IFF_UP, 0); > } > > @@ -794,10 +838,78 @@ int system_if_down(struct device *dev) > return ret; > } > > +struct if_check_data { > + struct device *dev; > + int pending; > + int ret; > +}; > + > +static int cb_if_check_valid(struct nl_msg *msg, void *arg) > +{ > + struct nlmsghdr *nh = nlmsg_hdr(msg); > + struct ifinfomsg *ifi = NLMSG_DATA(nh); > + struct if_check_data *chk = (struct if_check_data *)arg; > + > + if (nh->nlmsg_type != RTM_NEWLINK) > + return NL_SKIP; > + > + device_set_present(chk->dev, ifi->ifi_index > 0 ? true : false); > + device_set_link(chk->dev, ifi->ifi_flags & IFF_LOWER_UP ? true : > false); > + > + return NL_OK; > +} > + > +static int cb_if_check_ack(struct nl_msg *msg, void *arg) > +{ > + struct if_check_data *chk = (struct if_check_data *)arg; > + chk->pending = 0; > + return NL_STOP; > +} > + > +static int cb_if_check_error(struct sockaddr_nl *nla, struct nlmsgerr > *err, void *arg) > +{ > + struct if_check_data *chk = (struct if_check_data *)arg; > + > + device_set_present(chk->dev, false); > + device_set_link(chk->dev, false); > + chk->pending = err->error; > + > + return NL_STOP; > +} > + > int system_if_check(struct device *dev) > { > - device_set_present(dev, (system_if_resolve(dev) > 0)); > - return 0; > + struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT); > + struct nl_msg *msg; > + struct ifinfomsg ifi = { > + .ifi_family = AF_UNSPEC, > + .ifi_index = 0, > + }; > + struct if_check_data chk = { > + .dev = dev, > + .pending = 1, > + }; > + int ret = 1; > + > + msg = nlmsg_alloc_simple(RTM_GETLINK, 0); > + if (!msg || nlmsg_append(msg, &ifi, sizeof(ifi), 0) || > + nla_put_string(msg, IFLA_IFNAME, dev->ifname)) > + goto out; > + > + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_if_check_valid, &chk); > + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, cb_if_check_ack, &chk); > + nl_cb_err(cb, NL_CB_CUSTOM, cb_if_check_error, &chk); > + > + nl_send_auto_complete(sock_rtnl, msg); > + while (chk.pending > 0) > + nl_recvmsgs(sock_rtnl, cb); > + > + nlmsg_free(msg); > + ret = chk.pending; > + > +out: > + nl_cb_put(cb); > + return ret; > } > > struct device * > @@ -915,14 +1027,10 @@ system_if_dump_info(struct device *dev, struct > blob_buf *b) > char buf[64], *s; > void *c; > int dir_fd; > - uint64_t val = 0; > > snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname); > dir_fd = open(buf, O_DIRECTORY); > > - if (read_uint64_file(dir_fd, "carrier", &val)) > - blobmsg_add_u8(b, "link", !!val); > - > memset(&ecmd, 0, sizeof(ecmd)); > memset(&ifr, 0, sizeof(ifr)); > strcpy(ifr.ifr_name, dev->ifname); > -- > 1.7.1 > >
_______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel