vcl: ldp support for ip_pktinfo

Type: improvement

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I3c15f38a4a3f5e92506059277948e7fca9cd8b55
This commit is contained in:
Florin Coras
2023-02-07 17:36:17 -08:00
committed by Dave Barach
parent 7c7231fc30
commit eff5f7aea8
4 changed files with 243 additions and 85 deletions

View File

@ -26,7 +26,7 @@
#include <stdarg.h>
#include <sys/resource.h>
#include <netinet/tcp.h>
#include <linux/udp.h>
#include <netinet/udp.h>
#include <vcl/ldp_socket_wrapper.h>
#include <vcl/ldp.h>
@ -1556,17 +1556,14 @@ __recv_chk (int fd, void *buf, size_t n, size_t buflen, int flags)
static inline int
ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n,
vppcom_endpt_tlv_t *ep_tlv, int flags,
vppcom_endpt_tlv_t *app_tlvs, int flags,
__CONST_SOCKADDR_ARG _addr, socklen_t addr_len)
{
const struct sockaddr *addr = SOCKADDR_GET_SA (_addr);
vppcom_endpt_t *ep = 0;
vppcom_endpt_t _ep;
if (ep_tlv)
{
_ep.app_data = *ep_tlv;
}
_ep.app_tlvs = app_tlvs;
if (addr)
{
@ -1679,6 +1676,97 @@ recvfrom (int fd, void *__restrict buf, size_t n, int flags,
return size;
}
static int
ldp_parse_cmsg (vls_handle_t vlsh, const struct msghdr *msg,
vppcom_endpt_tlv_t **app_tlvs)
{
uint8_t *ad, *at = (uint8_t *) *app_tlvs;
vppcom_endpt_tlv_t *adh;
struct in_pktinfo *pi;
struct cmsghdr *cmsg;
cmsg = CMSG_FIRSTHDR (msg);
while (cmsg != NULL)
{
switch (cmsg->cmsg_level)
{
case SOL_UDP:
switch (cmsg->cmsg_type)
{
case UDP_SEGMENT:
vec_add2 (at, adh, sizeof (*adh));
adh->data_type = VCL_UDP_SEGMENT;
adh->data_len = sizeof (uint16_t);
vec_add2 (at, ad, sizeof (uint16_t));
*(uint16_t *) ad = *(uint16_t *) CMSG_DATA (cmsg);
break;
default:
LDBG (1, "SOL_UDP cmsg_type %u not supported", cmsg->cmsg_type);
break;
}
break;
case SOL_IP:
switch (cmsg->cmsg_type)
{
case IP_PKTINFO:
vec_add2 (at, adh, sizeof (*adh));
adh->data_type = VCL_IP_PKTINFO;
adh->data_len = sizeof (struct in_addr);
vec_add2 (at, ad, sizeof (struct in_addr));
pi = (void *) CMSG_DATA (cmsg);
clib_memcpy_fast (ad, &pi->ipi_spec_dst,
sizeof (struct in_addr));
break;
default:
LDBG (1, "SOL_IP cmsg_type %u not supported", cmsg->cmsg_type);
break;
}
break;
default:
LDBG (1, "cmsg_level %u not supported", cmsg->cmsg_level);
break;
}
cmsg = CMSG_NXTHDR ((struct msghdr *) msg, cmsg);
}
*app_tlvs = (vppcom_endpt_tlv_t *) at;
return 0;
}
static int
ldp_make_cmsg (vls_handle_t vlsh, struct msghdr *msg)
{
u32 optval, optlen = sizeof (optval);
struct cmsghdr *cmsg;
cmsg = CMSG_FIRSTHDR (msg);
if (!vls_attr (vlsh, VPPCOM_ATTR_GET_IP_PKTINFO, (void *) &optval, &optlen))
return 0;
if (optval)
{
vppcom_endpt_t ep;
u8 addr_buf[sizeof (struct in_addr)];
u32 size = sizeof (ep);
ep.ip = addr_buf;
if (!vls_attr (vlsh, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size))
{
struct in_pktinfo pi = {};
clib_memcpy (&pi.ipi_addr, ep.ip, sizeof (struct in_addr));
cmsg->cmsg_level = SOL_IP;
cmsg->cmsg_type = IP_PKTINFO;
cmsg->cmsg_len = CMSG_LEN (sizeof (pi));
clib_memcpy (CMSG_DATA (cmsg), &pi, sizeof (pi));
}
}
return 0;
}
ssize_t
sendmsg (int fd, const struct msghdr * msg, int flags)
{
@ -1690,29 +1778,17 @@ sendmsg (int fd, const struct msghdr * msg, int flags)
vlsh = ldp_fd_to_vlsh (fd);
if (vlsh != VLS_INVALID_HANDLE)
{
vppcom_endpt_tlv_t *app_tlvs = 0;
struct iovec *iov = msg->msg_iov;
ssize_t total = 0;
int i, rv = 0;
struct cmsghdr *cmsg;
uint16_t *valp;
vppcom_endpt_tlv_t _app_data;
vppcom_endpt_tlv_t *p_app_data = NULL;
cmsg = CMSG_FIRSTHDR (msg);
if (cmsg && cmsg->cmsg_type == UDP_SEGMENT)
{
p_app_data = &_app_data;
valp = (void *) CMSG_DATA (cmsg);
p_app_data->data_type = VCL_UDP_SEGMENT;
p_app_data->data_len = sizeof (*valp);
p_app_data->value = *valp;
}
ldp_parse_cmsg (vlsh, msg, &app_tlvs);
for (i = 0; i < msg->msg_iovlen; ++i)
{
rv =
ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, p_app_data,
flags, msg->msg_name, msg->msg_namelen);
rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, app_tlvs,
flags, msg->msg_name, msg->msg_namelen);
if (rv < 0)
break;
else
@ -1723,6 +1799,8 @@ sendmsg (int fd, const struct msghdr * msg, int flags)
}
}
vec_free (app_tlvs);
if (rv < 0 && total == 0)
{
errno = -rv;
@ -1828,7 +1906,11 @@ recvmsg (int fd, struct msghdr * msg, int flags)
size = -1;
}
else
size = total;
{
if (msg->msg_controllen)
ldp_make_cmsg (vlsh, msg);
size = total;
}
}
else
{
@ -2114,6 +2196,21 @@ setsockopt (int fd, int level, int optname,
break;
}
break;
case SOL_IP:
switch (optname)
{
case IP_PKTINFO:
rv = vls_attr (vlsh, VPPCOM_ATTR_SET_IP_PKTINFO, (void *) optval,
&optlen);
break;
default:
LDBG (0,
"ERROR: fd %d: setsockopt SOL_IP: vlsh %u optname %d"
"unsupported!",
fd, vlsh, optname);
break;
}
break;
default:
break;
}