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; +} |
