diff options
| author | Mark Stapp <mjs@labn.net> | 2023-03-29 16:58:25 -0400 | 
|---|---|---|
| committer | Mark Stapp <mjs@labn.net> | 2023-04-11 10:16:07 -0400 | 
| commit | 04a0401f2de44feaadb8f90aae0f53f55580415e (patch) | |
| tree | 2977bbd8a315abd0b5389735360d2f80fbf68503 /ospfd/ospf_network.c | |
| parent | e80c797a1f8f98c129a9605a174d451356dde008 (diff) | |
ospfd: support write socket per interface
Add support for a write socket per interface, enabled by
default at the ospf instance level. An ospf instance-level
config allows this to be disabled, reverting to the older
behavior where a single per-instance socket is used for
sending and receiving packets.
Signed-off-by: Mark Stapp <mjs@labn.net>
Diffstat (limited to 'ospfd/ospf_network.c')
| -rw-r--r-- | ospfd/ospf_network.c | 114 | 
1 files changed, 94 insertions, 20 deletions
diff --git a/ospfd/ospf_network.c b/ospfd/ospf_network.c index bd5cd7682a..aff8ed05c7 100644 --- a/ospfd/ospf_network.c +++ b/ospfd/ospf_network.c @@ -15,6 +15,7 @@  #include "sockopt.h"  #include "privs.h"  #include "lib_errors.h" +#include "lib/table.h"  #include "ospfd/ospfd.h"  #include "ospfd/ospf_network.h" @@ -119,61 +120,60 @@ int ospf_if_drop_alldrouters(struct ospf *top, struct prefix *p,  	return ret;  } -int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex) +int ospf_if_ipmulticast(int fd, struct prefix *p, ifindex_t ifindex)  {  	uint8_t val;  	int ret, len;  	/* Prevent receiving self-origined multicast packets. */ -	ret = setsockopt_ipv4_multicast_loop(top->fd, 0); +	ret = setsockopt_ipv4_multicast_loop(fd, 0);  	if (ret < 0)  		flog_err(EC_LIB_SOCKET,  			 "can't setsockopt IP_MULTICAST_LOOP(0) for fd %d: %s", -			 top->fd, safe_strerror(errno)); +			 fd, safe_strerror(errno));  	/* Explicitly set multicast ttl to 1 -- endo. */  	val = 1;  	len = sizeof(val); -	ret = setsockopt(top->fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, -			 len); +	ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&val, len);  	if (ret < 0)  		flog_err(EC_LIB_SOCKET,  			 "can't setsockopt IP_MULTICAST_TTL(1) for fd %d: %s", -			 top->fd, safe_strerror(errno)); +			 fd, safe_strerror(errno));  #ifndef GNU_LINUX  	/* For GNU LINUX ospf_write uses IP_PKTINFO, in_pktinfo to send  	 * packet out of ifindex. Below would be used Non Linux system.  	 */ -	ret = setsockopt_ipv4_multicast_if(top->fd, p->u.prefix4, ifindex); +	ret = setsockopt_ipv4_multicast_if(fd, p->u.prefix4, ifindex);  	if (ret < 0)  		flog_err(EC_LIB_SOCKET,  			 "can't setsockopt IP_MULTICAST_IF(fd %d, addr %pI4, ifindex %u): %s", -			 top->fd, &p->u.prefix4, ifindex, +			 fd, &p->u.prefix4, ifindex,  			 safe_strerror(errno));  #endif  	return ret;  } -int ospf_sock_init(struct ospf *ospf) +/* + * Helper to open and set up a socket; returns the new fd on success, + * -1 on error. + */ +static int sock_init_common(vrf_id_t vrf_id, const char *name, int *pfd)  {  	int ospf_sock;  	int ret, hincl = 1; -	/* silently ignore. already done */ -	if (ospf->fd > 0) -		return -1; - -	if (ospf->vrf_id == VRF_UNKNOWN) { +	if (vrf_id == VRF_UNKNOWN) {  		/* silently return since VRF is not ready */  		return -1;  	} +  	frr_with_privs(&ospfd_privs) {  		ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP, -				       ospf->vrf_id, ospf->name); +				       vrf_id, name);  		if (ospf_sock < 0) { -			flog_err(EC_LIB_SOCKET, -				 "ospf_read_sock_init: socket: %s", +			flog_err(EC_LIB_SOCKET, "%s: socket: %s", __func__,  				 safe_strerror(errno));  			return -1;  		} @@ -212,10 +212,8 @@ int ospf_sock_init(struct ospf *ospf)  				 ospf_sock);  	} -	/* Update socket buffer sizes */ -	ospf_sock_bufsize_update(ospf, ospf_sock, OSPF_SOCK_BOTH); +	*pfd = ospf_sock; -	ospf->fd = ospf_sock;  	return ret;  } @@ -237,3 +235,79 @@ void ospf_sock_bufsize_update(const struct ospf *ospf, int sock,  		setsockopt_so_sendbuf(sock, bufsize);  	}  } + +int ospf_sock_init(struct ospf *ospf) +{ +	int ret; + +	/* silently ignore. already done */ +	if (ospf->fd > 0) +		return -1; + +	ret = sock_init_common(ospf->vrf_id, ospf->name, &(ospf->fd)); + +	if (ret >= 0) /* Update socket buffer sizes */ +		ospf_sock_bufsize_update(ospf, ospf->fd, OSPF_SOCK_BOTH); + +	return ret; +} + +/* + * Open per-interface write socket + */ +int ospf_ifp_sock_init(struct interface *ifp) +{ +	struct ospf_if_info *oii; +	struct ospf_interface *oi; +	struct ospf *ospf; +	struct route_node *rn; +	int ret; + +	oii = IF_OSPF_IF_INFO(ifp); +	if (oii == NULL) +		return -1; + +	if (oii->oii_fd > 0) +		return 0; + +	rn = route_top(IF_OIFS(ifp)); +	if (rn && rn->info) { +		oi = rn->info; +		ospf = oi->ospf; +	} else +		return -1; + +	ret = sock_init_common(ifp->vrf->vrf_id, ifp->name, &oii->oii_fd); + +	if (ret >= 0) /* Update socket buffer sizes */ +		ospf_sock_bufsize_update(ospf, oii->oii_fd, OSPF_SOCK_BOTH); + +	if (IS_DEBUG_OSPF_EVENT) +		zlog_debug("%s: ifp %s, oii %p, fd %d", __func__, ifp->name, +			   oii, oii->oii_fd); + +	return ret; +} + +/* + * Close per-interface write socket + */ +int ospf_ifp_sock_close(struct interface *ifp) +{ +	struct ospf_if_info *oii; + +	oii = IF_OSPF_IF_INFO(ifp); +	if (oii == NULL) +		return 0; + +	if (oii->oii_fd > 0) { +		if (IS_DEBUG_OSPF_EVENT) +			zlog_debug("%s: ifp %s, oii %p, fd %d", __func__, +				   ifp->name, oii, oii->oii_fd); + +		close(oii->oii_fd); +		oii->oii_fd = -1; +	} + +	return 0; +}  | 
