mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
netlink: migrate to context
For SMP case, it was desirable to have a netlink listener per pt so they could deal with pt-level changes in the pt's local service thread. But Linux restricts the process to just one netlink listener. We worked around it by only listening on pt[0], this aligns us a bit more with the reality and moves to a single routing table in the context. There's still more to do for SMP case locking.
This commit is contained in:
parent
8dbe8507a3
commit
f9c3d432a8
10 changed files with 89 additions and 62 deletions
|
@ -311,7 +311,7 @@ solo:
|
|||
lwsi_set_state(wsi, LRS_WAITING_DNS);
|
||||
|
||||
lwsl_info("%s: %s: lookup %s:%u\n", __func__, wsi->lc.gutag, ads, port);
|
||||
(void)port;
|
||||
wsi->conn_port = (uint16_t)port;
|
||||
|
||||
#if defined(LWS_WITH_DETAILED_LATENCY)
|
||||
wsi->detlat.earliest_write_req_pre_write = lws_now_usecs();
|
||||
|
|
|
@ -129,7 +129,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
|
|||
#endif
|
||||
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
|
||||
const struct sockaddr *psa = NULL;
|
||||
uint16_t port = wsi->c_port;
|
||||
uint16_t port = wsi->conn_port;
|
||||
const char *cce, *iface;
|
||||
lws_dns_sort_t *curr;
|
||||
ssize_t plen = 0;
|
||||
|
|
|
@ -106,6 +106,7 @@ lws_client_connect_4_established(struct lws *wsi, struct lws *wsi_piggyback,
|
|||
lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_PROXY_RESPONSE,
|
||||
(int)wsi->a.context->timeout_secs);
|
||||
|
||||
wsi->conn_port = wsi->c_port;
|
||||
lwsi_set_state(wsi, LRS_WAITING_PROXY_REPLY);
|
||||
|
||||
return wsi;
|
||||
|
|
|
@ -562,7 +562,7 @@ lws_sort_dns_dump(struct lws *wsi)
|
|||
(void)n; /* nologs */
|
||||
|
||||
if (!lws_dll2_get_head(&wsi->dns_sorted_list))
|
||||
lwsl_info("%s: empty\n", __func__);
|
||||
lwsl_notice("%s: empty\n", __func__);
|
||||
|
||||
lws_start_foreach_dll(struct lws_dll2 *, d,
|
||||
lws_dll2_get_head(&wsi->dns_sorted_list)) {
|
||||
|
@ -572,7 +572,7 @@ lws_sort_dns_dump(struct lws *wsi)
|
|||
lws_sa46_write_numeric_address(&s->dest, dest, sizeof(dest));
|
||||
lws_sa46_write_numeric_address(&s->gateway, gw, sizeof(gw));
|
||||
|
||||
lwsl_info("%s: %d: (%d)%s, gw (%d)%s, idi: %d, "
|
||||
lwsl_notice("%s: %d: (%d)%s, gw (%d)%s, idi: %d, "
|
||||
"lbl: %d, prec: %d\n",
|
||||
__func__, n++, s->dest.sa4.sin_family, dest,
|
||||
s->gateway.sa4.sin_family, gw,
|
||||
|
@ -648,12 +648,13 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result)
|
|||
* we don't have a way to use it if we listed it
|
||||
*/
|
||||
|
||||
if (pt->routing_table.count) {
|
||||
if (pt->context->routing_table.count) {
|
||||
|
||||
estr = _lws_route_est_outgoing(pt, &ds->dest);
|
||||
if (!estr) {
|
||||
lws_free(ds);
|
||||
lwsl_info("%s: no route out\n", __func__);
|
||||
lwsl_notice("%s: %s has no route out\n",
|
||||
__func__, afip);
|
||||
/*
|
||||
* There's no outbound route for this, it's
|
||||
* unusable, so don't add it to the list
|
||||
|
@ -716,7 +717,7 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result)
|
|||
*/
|
||||
|
||||
lws_start_foreach_dll(struct lws_dll2 *, d,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&pt->context->routing_table)) {
|
||||
lws_route_t *r = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
/* gateway routes are skipped here */
|
||||
|
@ -731,7 +732,7 @@ lws_sort_dns(struct lws *wsi, const struct addrinfo *result)
|
|||
|
||||
/* bestsrc is the best source route, or NULL if none */
|
||||
|
||||
if (!bestsrc && pt->routing_table.count) {
|
||||
if (!bestsrc && pt->context->routing_table.count) {
|
||||
/* drop it, no usable source route */
|
||||
lws_free(ds);
|
||||
goto next;
|
||||
|
|
|
@ -881,7 +881,18 @@ lws_sa46_write_numeric_address(lws_sockaddr46 *sa46, char *buf, size_t len)
|
|||
return lws_write_numeric_address(
|
||||
(uint8_t *)&sa46->sa4.sin_addr, 4, buf, len);
|
||||
|
||||
lws_snprintf(buf, len, "(bad AF %d)", (int)sa46->sa4.sin_family);
|
||||
#if defined(LWS_WITH_UNIX_SOCK)
|
||||
if (sa46->sa4.sin_family == AF_UNIX)
|
||||
return lws_snprintf(buf, len, "(unix skt)");
|
||||
#endif
|
||||
|
||||
if (!sa46->sa4.sin_family)
|
||||
return lws_snprintf(buf, len, "(unset)");
|
||||
|
||||
if (sa46->sa4.sin_family == AF_INET6)
|
||||
lws_snprintf(buf, len, "(ipv6 unsupp)");
|
||||
|
||||
lws_snprintf(buf, len, "(AF%d unsupp)", (int)sa46->sa4.sin_family);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -298,7 +298,7 @@ __insert_wsi_socket_into_fds(struct lws_context *context, struct lws *wsi)
|
|||
assert(wsi);
|
||||
|
||||
#if defined(LWS_WITH_NETLINK)
|
||||
assert(wsi->event_pipe || wsi->a.vhost || wsi == pt->netlink);
|
||||
assert(wsi->event_pipe || wsi->a.vhost || wsi == pt->context->netlink);
|
||||
#else
|
||||
assert(wsi->event_pipe || wsi->a.vhost);
|
||||
#endif
|
||||
|
|
|
@ -402,11 +402,6 @@ struct lws_context_per_thread {
|
|||
lws_sockfd_type dummy_pipe_fds[2];
|
||||
struct lws *pipe_wsi;
|
||||
|
||||
#if defined(LWS_WITH_NETLINK)
|
||||
lws_dll2_owner_t routing_table;
|
||||
struct lws *netlink;
|
||||
#endif
|
||||
|
||||
/* --- role based members --- */
|
||||
|
||||
#if defined(LWS_ROLE_WS) && !defined(LWS_WITHOUT_EXTENSIONS)
|
||||
|
@ -450,10 +445,6 @@ struct lws_context_per_thread {
|
|||
|
||||
unsigned char tid;
|
||||
|
||||
#if defined(LWS_WITH_NETLINK)
|
||||
lws_route_uidx_t route_uidx;
|
||||
#endif
|
||||
|
||||
unsigned char inside_service:1;
|
||||
unsigned char inside_lws_service:1;
|
||||
unsigned char event_loop_foreign:1;
|
||||
|
@ -889,7 +880,7 @@ struct lws {
|
|||
unsigned int sock_send_blocking:1;
|
||||
#endif
|
||||
|
||||
uint16_t ocport, c_port;
|
||||
uint16_t ocport, c_port, conn_port;
|
||||
uint16_t retry;
|
||||
#if defined(LWS_WITH_CLIENT)
|
||||
uint16_t keep_warm_secs;
|
||||
|
@ -1411,7 +1402,7 @@ void
|
|||
_lws_routing_entry_dump(lws_route_t *rou);
|
||||
|
||||
void
|
||||
_lws_routing_table_dump(struct lws_context_per_thread *pt);
|
||||
_lws_routing_table_dump(struct lws_context *cx);
|
||||
|
||||
#define LRR_IGNORE_PRI (1 << 0)
|
||||
#define LRR_MATCH_SRC (1 << 1)
|
||||
|
@ -1426,7 +1417,7 @@ void
|
|||
_lws_route_table_ifdown(struct lws_context_per_thread *pt, int idx);
|
||||
|
||||
lws_route_uidx_t
|
||||
_lws_route_get_uidx(struct lws_context_per_thread *pt);
|
||||
_lws_route_get_uidx(struct lws_context *cx);
|
||||
|
||||
int
|
||||
_lws_route_pt_close_route_users(struct lws_context_per_thread *pt,
|
||||
|
|
|
@ -31,28 +31,43 @@
|
|||
#include <private-lib-core.h>
|
||||
|
||||
#if defined(_DEBUG)
|
||||
|
||||
|
||||
|
||||
void
|
||||
_lws_routing_entry_dump(lws_route_t *rou)
|
||||
{
|
||||
char sa[48], da[48], gw[48];
|
||||
char sa[48], fin[192], *end = &fin[sizeof(fin)];
|
||||
int n = 0;
|
||||
|
||||
lws_sa46_write_numeric_address(&rou->src, sa, sizeof(sa));
|
||||
lws_sa46_write_numeric_address(&rou->dest, da, sizeof(da));
|
||||
lws_sa46_write_numeric_address(&rou->gateway, gw, sizeof(gw));
|
||||
if (rou->dest.sa4.sin_family) {
|
||||
lws_sa46_write_numeric_address(&rou->dest, sa, sizeof(sa));
|
||||
n += lws_snprintf(fin, lws_ptr_diff_size_t(end, fin),
|
||||
"dst: %s/%d, ", sa, rou->dest_len);
|
||||
}
|
||||
|
||||
lwsl_info(" dst: (%d)%s/%d, src: (%d)%s/%d, gw: (%d)%s, ifidx: %d, pri: %d, proto: %d\n",
|
||||
rou->dest.sa4.sin_family, da, rou->dest_len,
|
||||
rou->src.sa4.sin_family, sa, rou->src_len,
|
||||
rou->gateway.sa4.sin_family, gw,
|
||||
rou->if_idx, rou->priority, rou->proto);
|
||||
if (rou->src.sa4.sin_family) {
|
||||
lws_sa46_write_numeric_address(&rou->src, sa, sizeof(sa));
|
||||
n += lws_snprintf(fin, lws_ptr_diff_size_t(end, fin),
|
||||
"src: %s/%d, ", sa, rou->src_len);
|
||||
}
|
||||
|
||||
if (rou->gateway.sa4.sin_family) {
|
||||
lws_sa46_write_numeric_address(&rou->gateway, sa, sizeof(sa));
|
||||
n += lws_snprintf(fin, lws_ptr_diff_size_t(end, fin),
|
||||
"gw: %s, ", sa);
|
||||
}
|
||||
|
||||
lwsl_info(" %s ifidx: %d, pri: %d, proto: %d\n", fin,
|
||||
rou->if_idx, rou->priority, rou->proto);
|
||||
}
|
||||
|
||||
void
|
||||
_lws_routing_table_dump(struct lws_context_per_thread *pt)
|
||||
_lws_routing_table_dump(struct lws_context *cx)
|
||||
{
|
||||
lwsl_info("%s\n", __func__);
|
||||
lws_start_foreach_dll(struct lws_dll2 *, d,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&cx->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
_lws_routing_entry_dump(rou);
|
||||
|
@ -80,10 +95,10 @@ _lws_routing_table_dump(struct lws_context_per_thread *pt)
|
|||
*/
|
||||
|
||||
lws_route_uidx_t
|
||||
_lws_route_get_uidx(struct lws_context_per_thread *pt)
|
||||
_lws_route_get_uidx(struct lws_context *cx)
|
||||
{
|
||||
if (!pt->route_uidx)
|
||||
pt->route_uidx++;
|
||||
if (!cx->route_uidx)
|
||||
cx->route_uidx++;
|
||||
|
||||
while (1) {
|
||||
char again = 0;
|
||||
|
@ -91,20 +106,20 @@ _lws_route_get_uidx(struct lws_context_per_thread *pt)
|
|||
/* Anybody in the table already uses the pt's next uidx? */
|
||||
|
||||
lws_start_foreach_dll(struct lws_dll2 *, d,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&cx->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
if (rou->uidx == pt->route_uidx) {
|
||||
if (rou->uidx == cx->route_uidx) {
|
||||
/* if so, bump and restart the check */
|
||||
pt->route_uidx++;
|
||||
if (!pt->route_uidx)
|
||||
pt->route_uidx++;
|
||||
cx->route_uidx++;
|
||||
if (!cx->route_uidx)
|
||||
cx->route_uidx++;
|
||||
again = 1;
|
||||
}
|
||||
} lws_end_foreach_dll(d);
|
||||
|
||||
if (!again)
|
||||
return pt->route_uidx++;
|
||||
return cx->route_uidx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +127,7 @@ int
|
|||
_lws_route_remove(struct lws_context_per_thread *pt, lws_route_t *robj, int flags)
|
||||
{
|
||||
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&pt->context->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
if ((!(flags & LRR_MATCH_SRC) || !lws_sa46_compare_ads(&robj->src, &rou->src)) &&
|
||||
|
@ -139,7 +154,7 @@ void
|
|||
_lws_route_table_empty(struct lws_context_per_thread *pt)
|
||||
{
|
||||
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&pt->context->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
lws_dll2_remove(&rou->list);
|
||||
lws_free(rou);
|
||||
|
@ -151,7 +166,7 @@ void
|
|||
_lws_route_table_ifdown(struct lws_context_per_thread *pt, int idx)
|
||||
{
|
||||
lws_start_foreach_dll_safe(struct lws_dll2 *, d, d1,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&pt->context->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
if (rou->if_idx == idx) {
|
||||
|
@ -183,7 +198,7 @@ _lws_route_est_outgoing(struct lws_context_per_thread *pt,
|
|||
*/
|
||||
|
||||
lws_start_foreach_dll(struct lws_dll2 *, d,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&pt->context->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
// _lws_routing_entry_dump(rou);
|
||||
|
@ -242,7 +257,7 @@ _lws_route_find_source(struct lws_context_per_thread *pt,
|
|||
const lws_sockaddr46 *src)
|
||||
{
|
||||
lws_start_foreach_dll(struct lws_dll2 *, d,
|
||||
lws_dll2_get_head(&pt->routing_table)) {
|
||||
lws_dll2_get_head(&pt->context->routing_table)) {
|
||||
lws_route_t *rou = lws_container_of(d, lws_route_t, list);
|
||||
|
||||
// _lws_routing_entry_dump(rou);
|
||||
|
@ -318,7 +333,7 @@ _lws_route_pt_close_unroutable(struct lws_context_per_thread *pt)
|
|||
|
||||
lwsl_debug("%s\n", __func__);
|
||||
#if defined(_DEBUG)
|
||||
_lws_routing_table_dump(pt);
|
||||
_lws_routing_table_dump(pt->context);
|
||||
#endif
|
||||
|
||||
for (n = 0; n < pt->fds_count; n++) {
|
||||
|
|
|
@ -405,6 +405,9 @@ struct lws_context {
|
|||
|
||||
#if defined(LWS_WITH_NETLINK)
|
||||
lws_sorted_usec_list_t sul_nl_coldplug;
|
||||
/* process can only have one netlink socket, have to do it in ctx */
|
||||
lws_dll2_owner_t routing_table;
|
||||
struct lws *netlink;
|
||||
#endif
|
||||
|
||||
#if defined(LWS_PLAT_FREERTOS) || defined(WIN32)
|
||||
|
@ -625,6 +628,10 @@ struct lws_context {
|
|||
uint16_t smd_queue_depth;
|
||||
#endif
|
||||
|
||||
#if defined(LWS_WITH_NETLINK)
|
||||
lws_route_uidx_t route_uidx;
|
||||
#endif
|
||||
|
||||
unsigned int deprecated:1;
|
||||
unsigned int inside_context_destroy:1;
|
||||
unsigned int being_destroyed:1;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#define RTA_ALIGNTO 4U
|
||||
|
||||
//#define lwsl_netlink lwsl_notice
|
||||
#define lwsl_netlink lwsl_debug
|
||||
#define lwsl_netlink lwsl_info
|
||||
|
||||
static void
|
||||
lws_netlink_coldplug_done_cb(lws_sorted_usec_list_t *sul)
|
||||
|
@ -58,6 +58,7 @@ static int
|
|||
rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi,
|
||||
struct lws_pollfd *pollfd)
|
||||
{
|
||||
struct lws_context *cx = pt->context;
|
||||
uint8_t s[4096]
|
||||
#if defined(_DEBUG)
|
||||
, route_change = 0
|
||||
|
@ -77,16 +78,16 @@ rops_handle_POLLIN_netlink(struct lws_context_per_thread *pt, struct lws *wsi,
|
|||
if (!(pollfd->revents & LWS_POLLIN))
|
||||
return LWS_HPI_RET_HANDLED;
|
||||
|
||||
if (!pt->context->nl_initial_done && pt == &pt->context->pt[0]) {
|
||||
if (!cx->nl_initial_done && pt == &cx->pt[0]) {
|
||||
/*
|
||||
* While netlink info still coming, keep moving the timer for
|
||||
* calling it "done" to +100ms until after it stops coming
|
||||
*/
|
||||
lws_context_lock(pt->context, __func__);
|
||||
lws_sul_schedule(pt->context, 0, &pt->context->sul_nl_coldplug,
|
||||
lws_context_lock(cx, __func__);
|
||||
lws_sul_schedule(cx, 0, &cx->sul_nl_coldplug,
|
||||
lws_netlink_coldplug_done_cb,
|
||||
100 * LWS_US_PER_MS);
|
||||
lws_context_unlock(pt->context);
|
||||
lws_context_unlock(cx);
|
||||
}
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
@ -388,8 +389,8 @@ ana:
|
|||
* cannot race
|
||||
*/
|
||||
|
||||
rou->uidx = _lws_route_get_uidx(pt);
|
||||
lws_dll2_add_tail(&rou->list, &pt->routing_table);
|
||||
rou->uidx = _lws_route_get_uidx(cx);
|
||||
lws_dll2_add_tail(&rou->list, &cx->routing_table);
|
||||
|
||||
_lws_route_pt_close_unroutable(pt);
|
||||
|
||||
|
@ -405,7 +406,7 @@ inform:
|
|||
* Participants interested can refer to the pt
|
||||
* routing table
|
||||
*/
|
||||
(void)lws_smd_msg_printf(pt->context, LWSSMDCL_NETWORK,
|
||||
(void)lws_smd_msg_printf(cx, LWSSMDCL_NETWORK,
|
||||
"{\"rt\":\"%s\"}\n",
|
||||
(h->nlmsg_type == RTM_DELROUTE) ?
|
||||
"del" : "add");
|
||||
|
@ -426,16 +427,16 @@ inform:
|
|||
* If a route with a gw was added or deleted, retrigger captive
|
||||
* portal detection if we have that
|
||||
*/
|
||||
(void)lws_smd_msg_printf(pt->context, LWSSMDCL_NETWORK,
|
||||
(void)lws_smd_msg_printf(cx, LWSSMDCL_NETWORK,
|
||||
"{\"trigger\": \"cpdcheck\", "
|
||||
"\"src\":\"gw-change\"}");
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG)
|
||||
if (route_change) {
|
||||
lws_pt_lock(pt, __func__);
|
||||
_lws_routing_table_dump(pt);
|
||||
lws_pt_unlock(pt);
|
||||
lws_context_lock(cx, __func__);
|
||||
_lws_routing_table_dump(cx);
|
||||
lws_context_unlock(cx);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -470,7 +471,7 @@ rops_pt_init_destroy_netlink(struct lws_context *context,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (pt->netlink)
|
||||
if (context->netlink)
|
||||
return 0;
|
||||
|
||||
if (pt > &context->pt[0])
|
||||
|
@ -515,7 +516,7 @@ rops_pt_init_destroy_netlink(struct lws_context *context,
|
|||
goto bail2;
|
||||
}
|
||||
|
||||
pt->netlink = wsi;
|
||||
context->netlink = wsi;
|
||||
if (lws_wsi_inject_to_loop(pt, wsi))
|
||||
goto bail2;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue