to->stateless_reset_token = src->stateless_reset_token;
}
-/* Retrieve the associated thread ID for <cid>. */
-static inline unsigned long quic_get_cid_tid(const unsigned char *cid)
+/* extract a TID from a CID for bind_conf <bc>, from 0 to global.nbthread-1 and
+ * in any case no more than 4095. It takes into account the bind_conf's thread
+ * group and the bind_conf's thread mask. The algorithm is the following: most
+ * packets contain a valid thread ID for the bind_conf, which means that the
+ * retrieved ID directly maps to a bound thread ID. If that's not the case,
+ * then we have to remap it. The resulting thread ID will then differ but will
+ * be correctly encoded and decoded.
+ */
+static inline uint quic_get_cid_tid(const unsigned char *cid, const struct bind_conf *bc)
{
- return *cid % global.nbthread;
+ uint id, grp;
+ uint base, count;
+
+ id = read_n16(cid) & 4095;
+ grp = bc->bind_tgroup;
+ base = ha_tgroup_info[grp - 1].base;
+ count = ha_tgroup_info[grp - 1].count;
+
+ if (base <= id && id < base + count &&
+ bc->bind_thread & ha_thread_info[id].ltid_bit)
+ return id; // part of the group and bound: valid
+
+ /* The thread number isn't valid, it doesn't map to a thread bound on
+ * this receiver. Let's reduce it to one of the thread(s) valid for
+ * that receiver.
+ */
+ count = my_popcountl(bc->bind_thread);
+ id = count - 1 - id % count;
+ id = mask_find_rank_bit(id, bc->bind_thread);
+ id += base;
+ return id;
}
-/* Modify <cid> to have a CID linked to the thread ID <target_tid>. This is
- * based on quic_get_cid_tid.
+/* Modify <cid> to have a CID linked to the thread ID <target_tid> that
+ * quic_get_cid_tid() will be able to extract return.
*/
-static inline void quic_pin_cid_to_tid(unsigned char *cid, int target_tid)
+static inline void quic_pin_cid_to_tid(unsigned char *cid, uint target_tid)
{
- cid[0] = MIN(cid[0], 255 - target_tid);
- cid[0] = cid[0] - (cid[0] % global.nbthread) + target_tid;
+ uint16_t prev_id;
+
+ prev_id = read_n16(cid);
+ write_n16(cid, (prev_id & ~4095) | target_tid);
}
/* Return a 32-bits integer in <val> from QUIC packet with <buf> as address.
/* Set tasklet tid based on the SCID selected by us for this
* connection. The upper layer will also be binded on the same thread.
*/
- qc->tid = qc->wait_event.tasklet->tid = quic_get_cid_tid(qc->scid.data);
+ qc->tid = quic_get_cid_tid(qc->scid.data, l->bind_conf);
+ qc->wait_event.tasklet->tid = qc->tid;
if (qc_conn_alloc_ssl_ctx(qc) ||
!quic_conn_init_timer(qc) ||