From 946195391406269003275850e1a4d550ea8db38b Mon Sep 17 00:00:00 2001 From: Mobashshera Rasool Date: Mon, 1 Aug 2022 23:12:53 -0700 Subject: [PATCH] pimd, pim6d: Send register msg via register socket The problem here is when the same node is FHR as well as RP, then the node keeps on sending the register packet. Register-stop is not sent as well. This problem has occurred because the RP is the same node and there is no socket created on loopback interface, so the packet is never send out and never received back on the same node, so register recv could not be processed on the node and hence no register-stop is sent. Since register packets are unicast packets, its better to handle the send of register packet via a separate register socket. This fixes the problem mentioned above as well. Fixes: #11331 Signed-off-by: Mobashshera Rasool --- pimd/pim_cmd_common.c | 2 ++ pimd/pim_instance.c | 7 +++++++ pimd/pim_instance.h | 1 + pimd/pim_register.c | 2 +- pimd/pim_sock.c | 40 ++++++++++++++++++++++++++++++++++++++++ pimd/pim_sock.h | 2 ++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c index b7bd7375c5..a04e36dbfc 100644 --- a/pimd/pim_cmd_common.c +++ b/pimd/pim_cmd_common.c @@ -3352,6 +3352,8 @@ void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty) vty_out(vty, "Mroute socket descriptor:"); vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name); + vty_out(vty, "PIM Register socket descriptor:"); + vty_out(vty, " %d(%s)\n", pim->reg_sock, vrf->name); pim_time_uptime(uptime, sizeof(uptime), now - pim->mroute_socket_creation); diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 359e3db718..4b85d45751 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -36,6 +36,7 @@ #include "pim_vty.h" #include "pim_bsm.h" #include "pim_mlag.h" +#include "pim_sock.h" static void pim_instance_terminate(struct pim_instance *pim) { @@ -70,6 +71,8 @@ static void pim_instance_terminate(struct pim_instance *pim) pim_msdp_exit(pim); + close(pim->reg_sock); + pim_mroute_socket_disable(pim); XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist); @@ -131,6 +134,10 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf) pim->last_route_change_time = -1; + pim->reg_sock = pim_reg_sock(); + if (pim->reg_sock < 0) + assert(0); + /* MSDP global timer defaults. */ pim->msdp.hold_time = PIM_MSDP_PEER_HOLD_TIME; pim->msdp.keep_alive = PIM_MSDP_PEER_KA_TIME; diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 684785dd13..0da881557c 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -136,6 +136,7 @@ struct pim_instance { struct thread *thread; int mroute_socket; + int reg_sock; /* Socket to send register msg */ int64_t mroute_socket_creation; int64_t mroute_add_events; int64_t mroute_add_last; diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 0eb49a7f91..4e2c44b172 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -331,7 +331,7 @@ void pim_register_send(const uint8_t *buf, int buf_size, pim_addr src, if (!pinfo->pim_passive_enable) ++pinfo->pim_ifstat_reg_send; - if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr, buffer, + if (pim_msg_send(pinfo->pim->reg_sock, src, rpg->rpf_addr, buffer, buf_size + PIM_MSG_REGISTER_LEN, ifp)) { if (PIM_DEBUG_PIM_TRACE) { zlog_debug( diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index afc5d47118..73184d5c63 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -179,6 +179,46 @@ static inline int pim_setsockopt(int protocol, int fd, struct interface *ifp) } #endif +int pim_reg_sock(void) +{ + int fd; + long flags; + + frr_with_privs (&pimd_privs) { + fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + } + + if (fd < 0) { + zlog_warn("Could not create raw socket: errno=%d: %s", errno, + safe_strerror(errno)); + return PIM_SOCK_ERR_SOCKET; + } + + if (sockopt_reuseaddr(fd)) { + close(fd); + return PIM_SOCK_ERR_REUSE; + } + + 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; +} + int pim_socket_mcast(int protocol, pim_addr ifaddr, struct interface *ifp, uint8_t loop) { diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h index ea9f7009bc..4dcb9e6466 100644 --- a/pimd/pim_sock.h +++ b/pimd/pim_sock.h @@ -51,4 +51,6 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len, int pim_socket_getsockname(int fd, struct sockaddr *name, socklen_t *namelen); +int pim_reg_sock(void); + #endif /* PIM_SOCK_H */ -- 2.39.5