Exemple #1
0
static void* rrl_runnable(void *arg)
{
	struct runnable_data* d = (struct runnable_data*)arg;
	sockaddr_t addr;
	memcpy(&addr, d->addr, sizeof(sockaddr_t));
	int lock = -1;
	uint32_t now = time(NULL);
	struct bucketmap_t *m = malloc(RRL_INSERTS * sizeof(struct bucketmap_t));
	for (unsigned i = 0; i < RRL_INSERTS; ++i) {
		m[i].i = knot_random_uint32_t(UINT32_MAX);
		addr.addr4.sin_addr.s_addr = m[i].i;
		rrl_item_t *b =  rrl_hash(d->rrl, &addr, d->rq, d->zone, now, &lock);
		rrl_unlock(d->rrl, lock);
		m[i].x = b->netblk;
	}
	for (unsigned i = 0; i < RRL_INSERTS; ++i) {
		addr.addr4.sin_addr.s_addr = m[i].i;
		rrl_item_t *b = rrl_hash(d->rrl, &addr, d->rq, d->zone, now, &lock);
		rrl_unlock(d->rrl, lock);
		if (b->netblk != m[i].x) {
			d->passed = 0;
		}
	}
	free(m);
	return NULL;
}
Exemple #2
0
int rrl_query(rrl_table_t *rrl, const struct sockaddr_storage *a, rrl_req_t *req,
              const zone_t *zone)
{
    if (!rrl || !req || !a) return KNOT_EINVAL;

    /* Calculate hash and fetch */
    int ret = KNOT_EOK;
    int lock = -1;
    uint32_t now = time(NULL);
    rrl_item_t *b = rrl_hash(rrl, a, req, zone, now, &lock);
    if (!b) {
        dbg_rrl("%s: failed to compute bucket from packet\n", __func__);
        if (lock > -1) rrl_unlock(rrl, lock);
        return KNOT_ERROR;
    }

    /* Calculate rate for dT */
    uint32_t dt = now - b->time;
    if (dt > RRL_CAPACITY) {
        dt = RRL_CAPACITY;
    }
    /* Visit bucket. */
    b->time = now;
    dbg_rrl("%s: bucket=0x%x tokens=%hu flags=%x dt=%u\n",
            __func__, (unsigned)(b - rrl->arr), b->ntok, b->flags, dt);
    if (dt > 0) { /* Window moved. */

        /* Check state change. */
        if ((b->ntok > 0 || dt > 1) && (b->flags & RRL_BF_ELIMIT)) {
            b->flags &= ~RRL_BF_ELIMIT;
            rrl_log_state(a, b->flags, b->cls);
        }

        /* Add new tokens. */
        uint32_t dn = rrl->rate * dt;
        if (b->flags & RRL_BF_SSTART) { /* Bucket in slow-start. */
            b->flags &= ~RRL_BF_SSTART;
            dbg_rrl("%s: bucket '0x%x' slow-start finished\n",
                    __func__, (unsigned)(b - rrl->arr));
        }
        b->ntok += dn;
        if (b->ntok > RRL_CAPACITY * rrl->rate) {
            b->ntok = RRL_CAPACITY * rrl->rate;
        }
    }

    /* Last item taken. */
    if (b->ntok == 1 && !(b->flags & RRL_BF_ELIMIT)) {
        b->flags |= RRL_BF_ELIMIT;
        rrl_log_state(a, b->flags, b->cls);
    }

    /* Decay current bucket. */
    if (b->ntok > 0) {
        --b->ntok;
    } else if (b->ntok == 0) {
        ret = KNOT_ELIMIT;
    }

    if (lock > -1) rrl_unlock(rrl, lock);
    return ret;
}