From 7923d3178ff6b5aab419a36869e777cb4be77636 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 19 Nov 2016 11:20:26 -0500 Subject: [PATCH] pimd: Cleanup igmp read socket With the change over to using the kernel upcall for igmp messages, we need to add in a read thread for the igmp socket to drain the igmp socket's receive queue. Signed-off-by: Donald Sharp --- pimd/pim_igmp.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++- pimd/pim_sock.c | 33 ++++++++++++++--------------- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index f47028b2ba..87a54d68d0 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -665,7 +665,6 @@ static void sock_close(struct igmp_sock *igmp) } } THREAD_OFF(igmp->t_igmp_read); - zassert(!igmp->t_igmp_read); if (close(igmp->fd)) { zlog_err("Failure closing IGMP socket %s fd=%d on interface %s: errno=%d: %s", @@ -841,6 +840,58 @@ static struct igmp_sock *igmp_sock_new(int fd, return igmp; } +static void igmp_read_on (struct igmp_sock *igmp); + +static int +pim_igmp_read (struct thread *t) +{ + uint8_t buf[10000]; + struct igmp_sock *igmp = (struct igmp_sock *)THREAD_ARG(t); + struct sockaddr_in from; + struct sockaddr_in to; + socklen_t fromlen = sizeof(from); + socklen_t tolen = sizeof(to); + ifindex_t ifindex = -1; + int cont = 1; + int len; + + while (cont) + { + len = pim_socket_recvfromto(igmp->fd, buf, sizeof(buf), + &from, &fromlen, + &to, &tolen, + &ifindex); + if (len < 0) + { + if (errno == EINTR) + continue; + if (errno == EWOULDBLOCK || errno == EAGAIN) + { + cont = 0; + break; + } + goto done; + } + } + + done: + igmp_read_on(igmp); + return 0; +} + +static void +igmp_read_on (struct igmp_sock *igmp) +{ + + if (PIM_DEBUG_IGMP_TRACE_DETAIL) { + zlog_debug("Scheduling READ event on IGMP socket fd=%d", + igmp->fd); + } + igmp->t_igmp_read = NULL; + THREAD_READ_ON(master, igmp->t_igmp_read, pim_igmp_read, igmp, igmp->fd); + +} + struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct in_addr ifaddr, struct interface *ifp) @@ -866,6 +917,8 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, return 0; } + igmp_read_on (igmp); + listnode_add(igmp_sock_list, igmp); #ifdef IGMP_SOCK_DUMP diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 6ce336d605..12f222bb80 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -230,25 +230,24 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, int ifindex, u_char lo zlog_warn("%s: Failure to set buffer size to %d", __PRETTY_FUNCTION__, rcvbuf); - if (protocol == IPPROTO_PIM) - { - long flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags < 0) { - zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_GETFL; - } + { + long flags; - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", - fd, errno, safe_strerror(errno)); - close(fd); - return PIM_SOCK_ERR_NONBLOCK_SETFL; - } + flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) { + zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_GETFL; + } + + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { + zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s", + fd, errno, safe_strerror(errno)); + close(fd); + return PIM_SOCK_ERR_NONBLOCK_SETFL; } + } return fd; } -- 2.39.5