Page MenuHomeFreeBSD

D57807.diff
No OneTemporary

D57807.diff

diff --git a/sys/netlink/netlink.h b/sys/netlink/netlink.h
--- a/sys/netlink/netlink.h
+++ b/sys/netlink/netlink.h
@@ -79,7 +79,7 @@
#define NETLINK_DROP_MEMBERSHIP 2 /* Unsubscribe from the specified group */
#define NETLINK_PKTINFO 3 /* XXX: not supported */
#define NETLINK_BROADCAST_ERROR 4 /* XXX: not supported */
-#define NETLINK_NO_ENOBUFS 5 /* XXX: not supported */
+#define NETLINK_NO_ENOBUFS 5 /* Suppress ENOBUFS on receive buffer overflow */
#define NETLINK_RX_RING 6 /* XXX: not supported */
#define NETLINK_TX_RING 7 /* XXX: not supported */
#define NETLINK_LISTEN_ALL_NSID 8 /* XXX: not supported */
diff --git a/sys/netlink/netlink_domain.c b/sys/netlink/netlink_domain.c
--- a/sys/netlink/netlink_domain.c
+++ b/sys/netlink/netlink_domain.c
@@ -696,8 +696,53 @@
msgrcv = 0;
datalen = 0;
+ if (__predict_false(nlp->nl_dropped_bytes > 0)) {
+ NLP_LOCK(nlp);
+ uint64_t dropped_bytes = nlp->nl_dropped_bytes;
+ uint64_t dropped_messages = nlp->nl_dropped_messages;
+ NLP_UNLOCK(nlp);
+
+ if (dropped_bytes > 0) {
+ NLP_LOG(LOG_DEBUG, nlp,
+ "socket RX overflowed, %ju messages (%ju bytes) dropped. "
+ "bytes: [%u/%u]", (uintmax_t)dropped_messages, (uintmax_t)dropped_bytes,
+ sb->sb_ccc, sb->sb_hiwat);
+ if (nlp->nl_linux) {
+ NLP_LOCK(nlp);
+ nlp->nl_dropped_bytes -= dropped_bytes;
+ nlp->nl_dropped_messages -= dropped_messages;
+ NLP_UNLOCK(nlp);
+ if (!(nlp->nl_flags & NLF_NO_ENOBUFS)) {
+ SOCK_IO_RECV_UNLOCK(so);
+ return (ENOBUFS);
+ }
+ } else {
+ if (uio->uio_resid >= sizeof(struct nlmsghdr)) {
+ struct nlmsghdr overrun = {
+ .nlmsg_len = sizeof(struct nlmsghdr),
+ .nlmsg_type = NLMSG_OVERRUN
+ /* XXX: could add dropped_{messages,bytes} as payload */
+ };
+ error = uiomove(&overrun, sizeof(overrun), uio);
+ if (error != 0) {
+ SOCK_IO_RECV_UNLOCK(so);
+ return (error);
+ }
+
+ if (!peek) {
+ NLP_LOCK(nlp);
+ nlp->nl_dropped_bytes -= dropped_bytes;
+ nlp->nl_dropped_messages -= dropped_messages;
+ NLP_UNLOCK(nlp);
+ }
+ msgrcv++;
+ }
+ }
+ }
+ }
+
SOCK_RECVBUF_LOCK(so);
- while ((first = TAILQ_FIRST(&sb->nl_queue)) == NULL) {
+ while ((first = TAILQ_FIRST(&sb->nl_queue)) == NULL && msgrcv == 0) {
if (nonblock) {
SOCK_RECVBUF_UNLOCK(so);
SOCK_IO_RECV_UNLOCK(so);
@@ -823,7 +868,9 @@
SOCK_IO_RECV_UNLOCK(so);
- nl_on_transmit(sotonlpcb(so));
+ NLP_LOCK(nlp);
+ nl_schedule_taskqueue(nlp);
+ NLP_UNLOCK(nlp);
return (error);
}
@@ -840,6 +887,8 @@
return (NLF_STRICT);
case NETLINK_MSG_INFO:
return (NLF_MSG_INFO);
+ case NETLINK_NO_ENOBUFS:
+ return (NLF_NO_ENOBUFS);
}
return (0);
@@ -881,6 +930,7 @@
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
case NETLINK_MSG_INFO:
+ case NETLINK_NO_ENOBUFS:
error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
if (error != 0)
break;
@@ -915,6 +965,7 @@
case NETLINK_EXT_ACK:
case NETLINK_GET_STRICT_CHK:
case NETLINK_MSG_INFO:
+ case NETLINK_NO_ENOBUFS:
NLCTL_RLOCK();
optval = (nlp->nl_flags & nl_getoptflag(sopt->sopt_name)) != 0;
NLCTL_RUNLOCK();
diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c
--- a/sys/netlink/netlink_io.c
+++ b/sys/netlink/netlink_io.c
@@ -154,33 +154,6 @@
;
}
-/*
- * Called after some data have been read from the socket.
- */
-void
-nl_on_transmit(struct nlpcb *nlp)
-{
- NLP_LOCK(nlp);
-
- struct socket *so = nlp->nl_socket;
- if (__predict_false(nlp->nl_dropped_bytes > 0 && so != NULL)) {
- unsigned long dropped_bytes = nlp->nl_dropped_bytes;
- unsigned long dropped_messages = nlp->nl_dropped_messages;
- nlp->nl_dropped_bytes = 0;
- nlp->nl_dropped_messages = 0;
-
- struct sockbuf *sb = &so->so_rcv;
- NLP_LOG(LOG_DEBUG, nlp,
- "socket RX overflowed, %lu messages (%lu bytes) dropped. "
- "bytes: [%u/%u]", dropped_messages, dropped_bytes,
- sb->sb_ccc, sb->sb_hiwat);
- /* TODO: send netlink message */
- }
-
- nl_schedule_taskqueue(nlp);
- NLP_UNLOCK(nlp);
-}
-
void
nl_taskqueue_handler(void *_arg, int pending)
{
diff --git a/sys/netlink/netlink_var.h b/sys/netlink/netlink_var.h
--- a/sys/netlink/netlink_var.h
+++ b/sys/netlink/netlink_var.h
@@ -91,6 +91,7 @@
#define NLF_EXT_ACK 0x02 /* Allow including extended TLVs in ack */
#define NLF_STRICT 0x04 /* Perform strict header checks */
#define NLF_MSG_INFO 0x08 /* Send caller info along with the notifications */
+#define NLF_NO_ENOBUFS 0x10 /* Do not report ENOBUFS on RX overflow */
SYSCTL_DECL(_net_netlink);
SYSCTL_DECL(_net_netlink_debug);
@@ -130,7 +131,6 @@
bool nl_send(struct nl_writer *, struct nlpcb *);
void nlmsg_ack(struct nlpcb *nlp, int error, struct nlmsghdr *nlmsg,
struct nl_pstate *npt);
-void nl_on_transmit(struct nlpcb *nlp);
void nl_taskqueue_handler(void *_arg, int pending);
void nl_schedule_taskqueue(struct nlpcb *nlp);

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 21, 12:25 PM (18 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37031122
Default Alt Text
D57807.diff (4 KB)

Event Timeline