lsquic_spi.c revision 5392f7a3
1229fce07SDmitri Tikhonov/* Copyright (c) 2017 - 2019 LiteSpeed Technologies Inc.  See LICENSE. */
250aadb33SDmitri Tikhonov/*
350aadb33SDmitri Tikhonov * lsquic_spi.c - implementation of Stream Priority Iterator.
450aadb33SDmitri Tikhonov */
550aadb33SDmitri Tikhonov
650aadb33SDmitri Tikhonov#include <assert.h>
750aadb33SDmitri Tikhonov#include <inttypes.h>
850aadb33SDmitri Tikhonov#include <stdint.h>
950aadb33SDmitri Tikhonov#include <stdlib.h>
10c51ce338SDmitri Tikhonov#include <string.h>
1150aadb33SDmitri Tikhonov#include <sys/queue.h>
1250aadb33SDmitri Tikhonov#include <sys/types.h>
13461e84d8SAmol Deshpande#ifdef WIN32
14461e84d8SAmol Deshpande#include <vc_compat.h>
15461e84d8SAmol Deshpande#endif
1650aadb33SDmitri Tikhonov
1750aadb33SDmitri Tikhonov#include "lsquic_types.h"
1850aadb33SDmitri Tikhonov#include "lsquic_int_types.h"
1950aadb33SDmitri Tikhonov#include "lsquic_sfcw.h"
205392f7a3SLiteSpeed Tech#include "lsquic_varint.h"
215392f7a3SLiteSpeed Tech#include "lsquic_hq.h"
225392f7a3SLiteSpeed Tech#include "lsquic_hash.h"
2350aadb33SDmitri Tikhonov#include "lsquic_stream.h"
2450aadb33SDmitri Tikhonov#include "lsquic_spi.h"
2550aadb33SDmitri Tikhonov
2650aadb33SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_SPI
275392f7a3SLiteSpeed Tech#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(iter->spi_conn)
2850aadb33SDmitri Tikhonov#include "lsquic_logger.h"
2950aadb33SDmitri Tikhonov
30461e84d8SAmol Deshpande#define SPI_DEBUG(fmt, ...) LSQ_DEBUG("%s: " fmt, iter->spi_name, __VA_ARGS__)
3150aadb33SDmitri Tikhonov
3250aadb33SDmitri Tikhonov#define NEXT_STREAM(stream, off) \
3350aadb33SDmitri Tikhonov    (* (struct lsquic_stream **) ((unsigned char *) (stream) + (off)))
3450aadb33SDmitri Tikhonov
3550aadb33SDmitri Tikhonov
3650aadb33SDmitri Tikhonovstatic void
3750aadb33SDmitri Tikhonovadd_stream_to_spi (struct stream_prio_iter *iter, lsquic_stream_t *stream)
3850aadb33SDmitri Tikhonov{
3950aadb33SDmitri Tikhonov    unsigned set, bit;
4050aadb33SDmitri Tikhonov    set = stream->sm_priority >> 6;
4150aadb33SDmitri Tikhonov    bit = stream->sm_priority & 0x3F;
4250aadb33SDmitri Tikhonov    if (!(iter->spi_set[set] & (1ULL << bit)))
4350aadb33SDmitri Tikhonov    {
4450aadb33SDmitri Tikhonov        iter->spi_set[set] |= 1ULL << bit;
4550aadb33SDmitri Tikhonov        TAILQ_INIT(&iter->spi_streams[ stream->sm_priority ]);
4650aadb33SDmitri Tikhonov    }
4750aadb33SDmitri Tikhonov    TAILQ_INSERT_TAIL(&iter->spi_streams[ stream->sm_priority ],
4850aadb33SDmitri Tikhonov                                                stream, next_prio_stream);
4950aadb33SDmitri Tikhonov}
5050aadb33SDmitri Tikhonov
5150aadb33SDmitri Tikhonov
5250aadb33SDmitri Tikhonovvoid
53c51ce338SDmitri Tikhonovlsquic_spi_init (struct stream_prio_iter *iter, struct lsquic_stream *first,
545392f7a3SLiteSpeed Tech         struct lsquic_stream *last, uintptr_t next_ptr_offset,
555392f7a3SLiteSpeed Tech         enum stream_q_flags onlist_mask, const struct lsquic_conn *conn,
565392f7a3SLiteSpeed Tech         const char *name,
575392f7a3SLiteSpeed Tech         int (*filter)(void *filter_ctx, struct lsquic_stream *),
585392f7a3SLiteSpeed Tech         void *filter_ctx)
5950aadb33SDmitri Tikhonov{
6050aadb33SDmitri Tikhonov    struct lsquic_stream *stream;
6150aadb33SDmitri Tikhonov    unsigned count;
6250aadb33SDmitri Tikhonov
635392f7a3SLiteSpeed Tech    iter->spi_conn          = conn;
6450aadb33SDmitri Tikhonov    iter->spi_name          = name ? name : "UNSET";
6550aadb33SDmitri Tikhonov    iter->spi_set[0]        = 0;
6650aadb33SDmitri Tikhonov    iter->spi_set[1]        = 0;
6750aadb33SDmitri Tikhonov    iter->spi_set[2]        = 0;
6850aadb33SDmitri Tikhonov    iter->spi_set[3]        = 0;
6950aadb33SDmitri Tikhonov    iter->spi_onlist_mask   = onlist_mask;
7050aadb33SDmitri Tikhonov    iter->spi_cur_prio      = 0;
7150aadb33SDmitri Tikhonov    iter->spi_prev_stream   = NULL;
7250aadb33SDmitri Tikhonov    iter->spi_next_stream   = NULL;
7350aadb33SDmitri Tikhonov
7450aadb33SDmitri Tikhonov    stream = first;
7550aadb33SDmitri Tikhonov    count = 0;
7650aadb33SDmitri Tikhonov
7719f667fbSDmitri Tikhonov    if (filter)
7819f667fbSDmitri Tikhonov        while (1)
7919f667fbSDmitri Tikhonov        {
8019f667fbSDmitri Tikhonov            if (filter(filter_ctx, stream))
8119f667fbSDmitri Tikhonov            {
8219f667fbSDmitri Tikhonov                add_stream_to_spi(iter, stream);
8319f667fbSDmitri Tikhonov                ++count;
8419f667fbSDmitri Tikhonov            }
8519f667fbSDmitri Tikhonov            if (stream == last)
8619f667fbSDmitri Tikhonov                break;
8719f667fbSDmitri Tikhonov            stream = NEXT_STREAM(stream, next_ptr_offset);
8819f667fbSDmitri Tikhonov        }
8919f667fbSDmitri Tikhonov    else
9019f667fbSDmitri Tikhonov        while (1)
9119f667fbSDmitri Tikhonov        {
9219f667fbSDmitri Tikhonov            add_stream_to_spi(iter, stream);
9319f667fbSDmitri Tikhonov            ++count;
9419f667fbSDmitri Tikhonov            if (stream == last)
9519f667fbSDmitri Tikhonov                break;
9619f667fbSDmitri Tikhonov            stream = NEXT_STREAM(stream, next_ptr_offset);
9719f667fbSDmitri Tikhonov        }
98c51ce338SDmitri Tikhonov
9950aadb33SDmitri Tikhonov    if (count > 2)
10050aadb33SDmitri Tikhonov        SPI_DEBUG("initialized; # elems: %u; sets: [ %016"PRIX64", %016"PRIX64
10150aadb33SDmitri Tikhonov            ", %016"PRIX64", %016"PRIX64" ]", count, iter->spi_set[0],
10250aadb33SDmitri Tikhonov            iter->spi_set[1], iter->spi_set[2], iter->spi_set[3]);
10350aadb33SDmitri Tikhonov}
10450aadb33SDmitri Tikhonov
10550aadb33SDmitri Tikhonov
10650aadb33SDmitri Tikhonovstatic int
10750aadb33SDmitri Tikhonovfind_and_set_lowest_priority (struct stream_prio_iter *iter)
10850aadb33SDmitri Tikhonov{
10950aadb33SDmitri Tikhonov    unsigned set, prio;
11050aadb33SDmitri Tikhonov    uint64_t mask;
11150aadb33SDmitri Tikhonov
11250aadb33SDmitri Tikhonov    for (set = 0, prio = 0; set < 4; ++set, prio += 64)
11350aadb33SDmitri Tikhonov        if (iter->spi_set[ set ])
11450aadb33SDmitri Tikhonov            break;
11550aadb33SDmitri Tikhonov
1168ca33e0eSDmitri Tikhonov    if (set >= 4)
11750aadb33SDmitri Tikhonov    {
11850aadb33SDmitri Tikhonov        //SPI_DEBUG("%s: cannot find any", __func__);
11950aadb33SDmitri Tikhonov        return -1;
12050aadb33SDmitri Tikhonov    }
12150aadb33SDmitri Tikhonov
12250aadb33SDmitri Tikhonov    mask = iter->spi_set[set];
12350aadb33SDmitri Tikhonov    if (!(mask & ((1ULL << 32) - 1))) { prio += 32; mask >>= 32; }
12450aadb33SDmitri Tikhonov    if (!(mask & ((1ULL << 16) - 1))) { prio += 16; mask >>= 16; }
12550aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  8) - 1))) { prio +=  8; mask >>=  8; }
12650aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  4) - 1))) { prio +=  4; mask >>=  4; }
12750aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  2) - 1))) { prio +=  2; mask >>=  2; }
12850aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  1) - 1))) { prio +=  1;              }
12950aadb33SDmitri Tikhonov
13050aadb33SDmitri Tikhonov#ifndef NDEBUG
13150aadb33SDmitri Tikhonov    unsigned bit;
13250aadb33SDmitri Tikhonov    set = prio >> 6;
13350aadb33SDmitri Tikhonov    bit = prio & 0x3F;
13450aadb33SDmitri Tikhonov    assert(iter->spi_set[ set ] & (1ULL << bit));
13550aadb33SDmitri Tikhonov#endif
13650aadb33SDmitri Tikhonov
13750aadb33SDmitri Tikhonov    SPI_DEBUG("%s: prio %u -> %u", __func__, iter->spi_cur_prio, prio);
1382d296031SDmitri Tikhonov    iter->spi_cur_prio = (unsigned char) prio;
13950aadb33SDmitri Tikhonov    return 0;
14050aadb33SDmitri Tikhonov}
14150aadb33SDmitri Tikhonov
14250aadb33SDmitri Tikhonov
14350aadb33SDmitri Tikhonovstatic int
14450aadb33SDmitri Tikhonovfind_and_set_next_priority (struct stream_prio_iter *iter)
14550aadb33SDmitri Tikhonov{
14650aadb33SDmitri Tikhonov    unsigned set, bit, prio;
14750aadb33SDmitri Tikhonov    uint64_t mask;
14850aadb33SDmitri Tikhonov
14950aadb33SDmitri Tikhonov    /* Examine values in the same set first */
15050aadb33SDmitri Tikhonov    set = iter->spi_cur_prio >> 6;
15150aadb33SDmitri Tikhonov    bit = iter->spi_cur_prio & 0x3F;
15250aadb33SDmitri Tikhonov    prio = 64 * set;
15350aadb33SDmitri Tikhonov
15450aadb33SDmitri Tikhonov    if (bit < 63)
15550aadb33SDmitri Tikhonov    {
15650aadb33SDmitri Tikhonov        mask = iter->spi_set[set];
15750aadb33SDmitri Tikhonov        mask &= ~((1ULL << (bit + 1)) - 1);
15850aadb33SDmitri Tikhonov        if (mask)
15950aadb33SDmitri Tikhonov            goto calc_priority;
16050aadb33SDmitri Tikhonov    }
16150aadb33SDmitri Tikhonov
16250aadb33SDmitri Tikhonov    ++set;
16350aadb33SDmitri Tikhonov    prio += 64;
16450aadb33SDmitri Tikhonov    for (; set < 4; ++set, prio += 64)
16550aadb33SDmitri Tikhonov        if (iter->spi_set[ set ])
16650aadb33SDmitri Tikhonov            break;
16750aadb33SDmitri Tikhonov
16803fb9352SDmitri Tikhonov    if (set >= 4)
16950aadb33SDmitri Tikhonov    {
17050aadb33SDmitri Tikhonov        //SPI_DEBUG("%s: cannot find any", __func__);
17150aadb33SDmitri Tikhonov        return -1;
17250aadb33SDmitri Tikhonov    }
17350aadb33SDmitri Tikhonov
17450aadb33SDmitri Tikhonov    mask = iter->spi_set[set];
17550aadb33SDmitri Tikhonov
17650aadb33SDmitri Tikhonov  calc_priority:
17750aadb33SDmitri Tikhonov    if (!(mask & ((1ULL << 32) - 1))) { prio += 32; mask >>= 32; }
17850aadb33SDmitri Tikhonov    if (!(mask & ((1ULL << 16) - 1))) { prio += 16; mask >>= 16; }
17950aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  8) - 1))) { prio +=  8; mask >>=  8; }
18050aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  4) - 1))) { prio +=  4; mask >>=  4; }
18150aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  2) - 1))) { prio +=  2; mask >>=  2; }
18250aadb33SDmitri Tikhonov    if (!(mask & ((1ULL <<  1) - 1))) { prio +=  1;              }
18350aadb33SDmitri Tikhonov
18450aadb33SDmitri Tikhonov#ifndef NDEBUG
18550aadb33SDmitri Tikhonov    set = prio >> 6;
18650aadb33SDmitri Tikhonov    bit = prio & 0x3F;
18750aadb33SDmitri Tikhonov    assert(iter->spi_set[ set ] & (1ULL << bit));
18850aadb33SDmitri Tikhonov#endif
18950aadb33SDmitri Tikhonov
19050aadb33SDmitri Tikhonov    SPI_DEBUG("%s: prio %u -> %u", __func__, iter->spi_cur_prio, prio);
1912d296031SDmitri Tikhonov    iter->spi_cur_prio = (unsigned char) prio;
19250aadb33SDmitri Tikhonov    return 0;
19350aadb33SDmitri Tikhonov}
19450aadb33SDmitri Tikhonov
19550aadb33SDmitri Tikhonov
19650aadb33SDmitri Tikhonov/* Each stream returned by the iterator is processed in some fashion.  If,
19750aadb33SDmitri Tikhonov * as a result of this, the stream gets taken off the original list, we
19850aadb33SDmitri Tikhonov * have to follow suit and remove it from the iterator's set of streams.
19950aadb33SDmitri Tikhonov */
20050aadb33SDmitri Tikhonovstatic void
20150aadb33SDmitri Tikhonovmaybe_evict_prev (struct stream_prio_iter *iter)
20250aadb33SDmitri Tikhonov{
20350aadb33SDmitri Tikhonov    unsigned set, bit;
20450aadb33SDmitri Tikhonov
2055392f7a3SLiteSpeed Tech    if (0 == (iter->spi_prev_stream->sm_qflags & iter->spi_onlist_mask))
20650aadb33SDmitri Tikhonov    {
2075392f7a3SLiteSpeed Tech        SPI_DEBUG("evict stream %"PRIu64, iter->spi_prev_stream->id);
20850aadb33SDmitri Tikhonov        TAILQ_REMOVE(&iter->spi_streams[ iter->spi_prev_prio ],
20950aadb33SDmitri Tikhonov                                    iter->spi_prev_stream, next_prio_stream);
21050aadb33SDmitri Tikhonov        if (TAILQ_EMPTY(&iter->spi_streams[ iter->spi_prev_prio ]))
21150aadb33SDmitri Tikhonov        {
21250aadb33SDmitri Tikhonov            set = iter->spi_prev_prio >> 6;
21350aadb33SDmitri Tikhonov            bit = iter->spi_prev_prio & 0x3F;
21450aadb33SDmitri Tikhonov            iter->spi_set[ set ] &= ~(1ULL << bit);
21550aadb33SDmitri Tikhonov            SPI_DEBUG("priority %u now has no elements", iter->spi_prev_prio);
21650aadb33SDmitri Tikhonov        }
21750aadb33SDmitri Tikhonov        iter->spi_prev_stream = NULL;
21850aadb33SDmitri Tikhonov    }
21950aadb33SDmitri Tikhonov}
22050aadb33SDmitri Tikhonov
22150aadb33SDmitri Tikhonov
22250aadb33SDmitri Tikhonovlsquic_stream_t *
22350aadb33SDmitri Tikhonovlsquic_spi_first (struct stream_prio_iter *iter)
22450aadb33SDmitri Tikhonov{
22550aadb33SDmitri Tikhonov    lsquic_stream_t *stream;
22650aadb33SDmitri Tikhonov    unsigned set, bit;
22750aadb33SDmitri Tikhonov
22850aadb33SDmitri Tikhonov    if (iter->spi_prev_stream)
22950aadb33SDmitri Tikhonov        maybe_evict_prev(iter);
23050aadb33SDmitri Tikhonov
23150aadb33SDmitri Tikhonov    iter->spi_cur_prio = 0;
23250aadb33SDmitri Tikhonov    set = iter->spi_cur_prio >> 6;
23350aadb33SDmitri Tikhonov    bit = iter->spi_cur_prio & 0x3F;
23450aadb33SDmitri Tikhonov
23550aadb33SDmitri Tikhonov    if (!(iter->spi_set[set] & (1ULL << bit)))
23650aadb33SDmitri Tikhonov    {
23750aadb33SDmitri Tikhonov        if (0 != find_and_set_lowest_priority(iter))
23850aadb33SDmitri Tikhonov        {
23950aadb33SDmitri Tikhonov            SPI_DEBUG("%s: return NULL", __func__);
24050aadb33SDmitri Tikhonov            return NULL;
24150aadb33SDmitri Tikhonov        }
24250aadb33SDmitri Tikhonov    }
24350aadb33SDmitri Tikhonov
24450aadb33SDmitri Tikhonov    stream = TAILQ_FIRST(&iter->spi_streams[ iter->spi_cur_prio ]);
24550aadb33SDmitri Tikhonov    iter->spi_prev_prio   = iter->spi_cur_prio;
24650aadb33SDmitri Tikhonov    iter->spi_prev_stream = stream;
24750aadb33SDmitri Tikhonov    iter->spi_next_stream = TAILQ_NEXT(stream, next_prio_stream);
2485392f7a3SLiteSpeed Tech    if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG) && !lsquic_stream_is_critical(stream))
2495392f7a3SLiteSpeed Tech        SPI_DEBUG("%s: return stream %"PRIu64", priority %u", __func__,
2505392f7a3SLiteSpeed Tech                                            stream->id, iter->spi_cur_prio);
25150aadb33SDmitri Tikhonov    return stream;
25250aadb33SDmitri Tikhonov}
25350aadb33SDmitri Tikhonov
25450aadb33SDmitri Tikhonov
25550aadb33SDmitri Tikhonovlsquic_stream_t *
25650aadb33SDmitri Tikhonovlsquic_spi_next (struct stream_prio_iter *iter)
25750aadb33SDmitri Tikhonov{
25850aadb33SDmitri Tikhonov    lsquic_stream_t *stream;
25950aadb33SDmitri Tikhonov
26050aadb33SDmitri Tikhonov    if (iter->spi_prev_stream)
26150aadb33SDmitri Tikhonov        maybe_evict_prev(iter);
26250aadb33SDmitri Tikhonov
26350aadb33SDmitri Tikhonov    stream = iter->spi_next_stream;
26450aadb33SDmitri Tikhonov    if (stream)
26550aadb33SDmitri Tikhonov    {
26650aadb33SDmitri Tikhonov        assert(iter->spi_prev_prio == iter->spi_cur_prio);
26750aadb33SDmitri Tikhonov        iter->spi_prev_stream = stream;
26850aadb33SDmitri Tikhonov        iter->spi_next_stream = TAILQ_NEXT(stream, next_prio_stream);
2695392f7a3SLiteSpeed Tech        if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG) && !lsquic_stream_is_critical(stream))
2705392f7a3SLiteSpeed Tech            SPI_DEBUG("%s: return stream %"PRIu64", priority %u", __func__,
2715392f7a3SLiteSpeed Tech                                            stream->id, iter->spi_cur_prio);
27250aadb33SDmitri Tikhonov        return stream;
27350aadb33SDmitri Tikhonov    }
27450aadb33SDmitri Tikhonov
27550aadb33SDmitri Tikhonov    if (0 != find_and_set_next_priority(iter))
27650aadb33SDmitri Tikhonov    {
27750aadb33SDmitri Tikhonov        //SPI_DEBUG("%s: return NULL", __func__);
27850aadb33SDmitri Tikhonov        return NULL;
27950aadb33SDmitri Tikhonov    }
28050aadb33SDmitri Tikhonov
28150aadb33SDmitri Tikhonov    stream = TAILQ_FIRST(&iter->spi_streams[ iter->spi_cur_prio ]);
28250aadb33SDmitri Tikhonov    iter->spi_prev_prio   = iter->spi_cur_prio;
28350aadb33SDmitri Tikhonov    iter->spi_prev_stream = stream;
28450aadb33SDmitri Tikhonov    iter->spi_next_stream = TAILQ_NEXT(stream, next_prio_stream);
28550aadb33SDmitri Tikhonov
2865392f7a3SLiteSpeed Tech    if (LSQ_LOG_ENABLED(LSQ_LOG_DEBUG) && !lsquic_stream_is_critical(stream))
2875392f7a3SLiteSpeed Tech        SPI_DEBUG("%s: return stream %"PRIu64", priority %u", __func__,
2885392f7a3SLiteSpeed Tech                                            stream->id, iter->spi_cur_prio);
28950aadb33SDmitri Tikhonov    return stream;
29050aadb33SDmitri Tikhonov}
29150aadb33SDmitri Tikhonov
29250aadb33SDmitri Tikhonov
293c51ce338SDmitri Tikhonovstatic int
294c51ce338SDmitri Tikhonovhave_non_critical_streams (const struct stream_prio_iter *iter)
295c51ce338SDmitri Tikhonov{
296c51ce338SDmitri Tikhonov    const struct lsquic_stream *stream;
297c51ce338SDmitri Tikhonov    TAILQ_FOREACH(stream, &iter->spi_streams[ iter->spi_cur_prio ],
298c51ce338SDmitri Tikhonov                                                        next_prio_stream)
299c51ce338SDmitri Tikhonov        if (!lsquic_stream_is_critical(stream))
300c51ce338SDmitri Tikhonov            return 1;
301c51ce338SDmitri Tikhonov    return 0;
302c51ce338SDmitri Tikhonov}
303c51ce338SDmitri Tikhonov
304c51ce338SDmitri Tikhonov
305c51ce338SDmitri Tikhonovstatic void
306c51ce338SDmitri Tikhonovspi_drop_high_or_non_high (struct stream_prio_iter *iter, int drop_high)
307c51ce338SDmitri Tikhonov{
308c51ce338SDmitri Tikhonov    uint64_t new_set[ sizeof(iter->spi_set) / sizeof(iter->spi_set[0]) ];
309c51ce338SDmitri Tikhonov    unsigned bit, set, n;
310c51ce338SDmitri Tikhonov
311c51ce338SDmitri Tikhonov    memset(new_set, 0, sizeof(new_set));
312c51ce338SDmitri Tikhonov
313c51ce338SDmitri Tikhonov    find_and_set_lowest_priority(iter);
314c51ce338SDmitri Tikhonov    set = iter->spi_cur_prio >> 6;
315c51ce338SDmitri Tikhonov    bit = iter->spi_cur_prio & 0x3F;
316c51ce338SDmitri Tikhonov    new_set[set] |= 1ULL << bit;
317c51ce338SDmitri Tikhonov
318c51ce338SDmitri Tikhonov    if (!have_non_critical_streams(iter))
319c51ce338SDmitri Tikhonov    {
320c51ce338SDmitri Tikhonov        ++iter->spi_cur_prio;
321c51ce338SDmitri Tikhonov        find_and_set_lowest_priority(iter);
322c51ce338SDmitri Tikhonov        set = iter->spi_cur_prio >> 6;
323c51ce338SDmitri Tikhonov        bit = iter->spi_cur_prio & 0x3F;
324c51ce338SDmitri Tikhonov        new_set[set] |= 1ULL << bit;
325c51ce338SDmitri Tikhonov    }
326c51ce338SDmitri Tikhonov
327c51ce338SDmitri Tikhonov    for (n = 0; n < sizeof(new_set) / sizeof(new_set[0]); ++n)
328c51ce338SDmitri Tikhonov        if (drop_high)
329c51ce338SDmitri Tikhonov            iter->spi_set[n] &= ~new_set[n];
330c51ce338SDmitri Tikhonov        else
331c51ce338SDmitri Tikhonov            iter->spi_set[n] = new_set[n];
332c51ce338SDmitri Tikhonov}
333c51ce338SDmitri Tikhonov
334c51ce338SDmitri Tikhonov
335c51ce338SDmitri Tikhonovvoid
336c51ce338SDmitri Tikhonovlsquic_spi_drop_high (struct stream_prio_iter *iter)
337c51ce338SDmitri Tikhonov{
338c51ce338SDmitri Tikhonov    spi_drop_high_or_non_high(iter, 1);
339c51ce338SDmitri Tikhonov}
340c51ce338SDmitri Tikhonov
341c51ce338SDmitri Tikhonov
34250aadb33SDmitri Tikhonovvoid
343c51ce338SDmitri Tikhonovlsquic_spi_drop_non_high (struct stream_prio_iter *iter)
34450aadb33SDmitri Tikhonov{
345c51ce338SDmitri Tikhonov    spi_drop_high_or_non_high(iter, 0);
34650aadb33SDmitri Tikhonov}
347