Page MenuHomeFreeBSD

D49100.diff
No OneTemporary

D49100.diff

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -339,6 +339,7 @@
* lookups until listen() has been called.
*/
LIST_INSERT_HEAD(&grp->il_pending, inp, inp_lbgroup_list);
+ grp->il_pendcnt++;
} else {
grp->il_inp[grp->il_inpcnt] = inp;
@@ -375,6 +376,8 @@
CK_LIST_INSERT_HEAD(hdr, grp, il_list);
LIST_SWAP(&old_grp->il_pending, &grp->il_pending, inpcb,
inp_lbgroup_list);
+ grp->il_pendcnt = old_grp->il_pendcnt;
+ old_grp->il_pendcnt = 0;
in_pcblbgroup_free(old_grp);
return (grp);
}
@@ -435,7 +438,7 @@
return (ENOBUFS);
in_pcblbgroup_insert(grp, inp);
CK_LIST_INSERT_HEAD(hdr, grp, il_list);
- } else if (grp->il_inpcnt == grp->il_inpsiz) {
+ } else if (grp->il_inpcnt + grp->il_pendcnt == grp->il_inpsiz) {
if (grp->il_inpsiz >= INPCBLBGROUP_SIZMAX) {
if (ratecheck(&lastprint, &interval))
printf("lb group port %d, limit reached\n",
@@ -499,6 +502,7 @@
LIST_FOREACH(inp1, &grp->il_pending, inp_lbgroup_list) {
if (inp == inp1) {
LIST_REMOVE(inp, inp_lbgroup_list);
+ grp->il_pendcnt--;
inp->inp_flags &= ~INP_INLBGROUP;
return;
}
@@ -1503,6 +1507,7 @@
INP_HASH_WLOCK(pcbinfo);
grp = in_pcblbgroup_find(inp);
LIST_REMOVE(inp, inp_lbgroup_list);
+ grp->il_pendcnt--;
in_pcblbgroup_insert(grp, inp);
INP_HASH_WUNLOCK(pcbinfo);
}
diff --git a/sys/netinet/in_pcb_var.h b/sys/netinet/in_pcb_var.h
--- a/sys/netinet/in_pcb_var.h
+++ b/sys/netinet/in_pcb_var.h
@@ -82,6 +82,7 @@
#define il6_laddr il_dependladdr.id6_addr
uint32_t il_inpsiz; /* max count in il_inp[] (h) */
uint32_t il_inpcnt; /* cur count in il_inp[] (h) */
+ uint32_t il_pendcnt; /* cur count in il_pending (h) */
struct inpcb *il_inp[]; /* (h) */
};
diff --git a/tests/sys/netinet/so_reuseport_lb_test.c b/tests/sys/netinet/so_reuseport_lb_test.c
--- a/tests/sys/netinet/so_reuseport_lb_test.c
+++ b/tests/sys/netinet/so_reuseport_lb_test.c
@@ -433,6 +433,51 @@
ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
}
+/*
+ * Try binding many sockets to the same lbgroup without calling listen(2) on
+ * them.
+ */
+ATF_TC_WITHOUT_HEAD(bind_without_listen);
+ATF_TC_BODY(bind_without_listen, tc)
+{
+ const int nsockets = 100;
+ struct sockaddr_in sin;
+ socklen_t socklen;
+ int error, s, s2[nsockets];
+
+ s = lb_listen_socket(PF_INET, 0);
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(0);
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ error = bind(s, (struct sockaddr *)&sin, sizeof(sin));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+
+ socklen = sizeof(sin);
+ error = getsockname(s, (struct sockaddr *)&sin, &socklen);
+ ATF_REQUIRE_MSG(error == 0, "getsockname() failed: %s",
+ strerror(errno));
+
+ for (int i = 0; i < nsockets; i++) {
+ s2[i] = lb_listen_socket(PF_INET, 0);
+ error = bind(s2[i], (struct sockaddr *)&sin, sizeof(sin));
+ ATF_REQUIRE_MSG(error == 0, "bind() failed: %s", strerror(errno));
+ }
+ for (int i = 0; i < nsockets; i++) {
+ error = listen(s2[i], 1);
+ ATF_REQUIRE_MSG(error == 0, "listen() failed: %s", strerror(errno));
+ }
+ for (int i = 0; i < nsockets; i++) {
+ error = close(s2[i]);
+ ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
+ }
+
+ error = close(s);
+ ATF_REQUIRE_MSG(error == 0, "close() failed: %s", strerror(errno));
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, basic_ipv4);
@@ -440,6 +485,7 @@
ATF_TP_ADD_TC(tp, concurrent_add);
ATF_TP_ADD_TC(tp, double_listen_ipv4);
ATF_TP_ADD_TC(tp, double_listen_ipv6);
+ ATF_TP_ADD_TC(tp, bind_without_listen);
return (atf_no_error());
}

File Metadata

Mime Type
text/plain
Expires
Tue, May 26, 5:20 PM (8 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33533930
Default Alt Text
D49100.diff (3 KB)

Event Timeline