summaryrefslogtreecommitdiff
path: root/accel-pppd/shaper
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd/shaper')
-rw-r--r--accel-pppd/shaper/limiter.c14
-rw-r--r--accel-pppd/shaper/shaper.c97
-rw-r--r--accel-pppd/shaper/shaper.h4
3 files changed, 93 insertions, 22 deletions
diff --git a/accel-pppd/shaper/limiter.c b/accel-pppd/shaper/limiter.c
index 6cc8d6c..c5da965 100644
--- a/accel-pppd/shaper/limiter.c
+++ b/accel-pppd/shaper/limiter.c
@@ -293,7 +293,7 @@ static int install_htb_ifb(struct rtnl_handle *rth, int ifindex, __u32 priority,
struct qdisc_opt opt1 = {
.kind = "htb",
- .handle = 0x00010001 + priority,
+ .handle = 0x00010000 + priority,
.parent = 0x00010000,
.rate = rate,
.buffer = burst,
@@ -445,14 +445,14 @@ static int remove_ingress(struct rtnl_handle *rth, int ifindex)
static int remove_htb_ifb(struct rtnl_handle *rth, int ifindex, int priority)
{
struct qdisc_opt opt = {
- .handle = 0x00010001 + priority,
+ .handle = 0x00010000 + priority,
.parent = 0x00010000,
};
return tc_qdisc_modify(rth, conf_ifb_ifindex, RTM_DELTCLASS, 0, &opt);
}
-int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst)
+int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst, int idx)
{
struct rtnl_handle rth;
int r;
@@ -478,9 +478,9 @@ int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int
if (conf_up_limiter == LIM_POLICE)
r = install_police(&rth, ses->ifindex, up_speed, up_burst);
else {
- r = install_htb_ifb(&rth, ses->ifindex, ses->unit_idx + 1, up_speed, up_burst);
+ r = install_htb_ifb(&rth, ses->ifindex, idx, up_speed, up_burst);
if (r == 0)
- r = install_leaf_qdisc(&rth, conf_ifb_ifindex, 0x00010001 + ses->unit_idx + 1, (1 + ses->unit_idx + 1) << 16);
+ r = install_leaf_qdisc(&rth, conf_ifb_ifindex, 0x00010000 + idx, idx << 16);
}
if (conf_fwmark)
@@ -491,7 +491,7 @@ int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int
return r;
}
-int remove_limiter(struct ap_session *ses)
+int remove_limiter(struct ap_session *ses, int idx)
{
struct rtnl_handle rth;
@@ -504,7 +504,7 @@ int remove_limiter(struct ap_session *ses)
remove_ingress(&rth, ses->ifindex);
if (conf_up_limiter == LIM_HTB)
- remove_htb_ifb(&rth, ses->ifindex, ses->unit_idx + 1);
+ remove_htb_ifb(&rth, ses->ifindex, idx);
rtnl_close(&rth);
diff --git a/accel-pppd/shaper/shaper.c b/accel-pppd/shaper/shaper.c
index 213b58f..f13290d 100644
--- a/accel-pppd/shaper/shaper.c
+++ b/accel-pppd/shaper/shaper.c
@@ -6,6 +6,7 @@
#include <linux/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
+#include <sys/mman.h>
#include <pthread.h>
#include "triton.h"
@@ -23,6 +24,10 @@
#include "shaper.h"
#include "tc_core.h"
+#ifndef __BITS_PER_LONG
+#define __BITS_PER_LONG (sizeof(long) * 8)
+#endif
+
#define ATTR_UP 1
#define ATTR_DOWN 2
@@ -74,6 +79,7 @@ struct shaper_pd_t {
struct list_head tr_list;
struct time_range_pd_t *cur_tr;
int refs;
+ int idx;
};
struct time_range_pd_t {
@@ -97,12 +103,57 @@ static void *pd_key;
static LIST_HEAD(time_range_list);
static int time_range_id = 0;
+#define MAX_IDX 65536
+static long *idx_map;
+
static void shaper_ctx_close(struct triton_context_t *);
static struct triton_context_t shaper_ctx = {
.close = shaper_ctx_close,
.before_switch = log_switch,
};
+static int alloc_idx(int init)
+{
+ int i, p = 0;
+
+ init %= MAX_IDX;
+
+ pthread_rwlock_wrlock(&shaper_lock);
+ if (idx_map[init / __BITS_PER_LONG] & (1 << (init % __BITS_PER_LONG))) {
+ i = init / __BITS_PER_LONG;
+ p = init % __BITS_PER_LONG;
+ } else {
+ for (i = init / __BITS_PER_LONG; i < MAX_IDX / __BITS_PER_LONG; i++) {
+ p = ffs(idx_map[i]);
+ if (p)
+ break;
+ }
+
+ if (!p) {
+ for (i = 0; i < init / __BITS_PER_LONG; i++) {
+ p = ffs(idx_map[i]);
+ if (p)
+ break;
+ }
+ }
+ }
+
+ if (p)
+ idx_map[i] &= ~(1 << (p - 1));
+
+ pthread_rwlock_unlock(&shaper_lock);
+
+ if (!p)
+ return 0;
+
+ return i * __BITS_PER_LONG + p - 1;
+}
+
+static void free_idx(int idx)
+{
+ idx_map[idx / __BITS_PER_LONG] |= 1 << (idx % __BITS_PER_LONG);
+}
+
static struct shaper_pd_t *find_pd(struct ap_session *ses, int create)
{
struct ap_private *pd;
@@ -320,7 +371,7 @@ static void ev_radius_coa(struct ev_radius_t *ev)
pd->up_speed = 0;
if (conf_verbose)
log_ppp_info2("shaper: removed shaper\n");
- remove_limiter(ev->ses);
+ remove_limiter(ev->ses, pd->idx);
}
return;
}
@@ -329,13 +380,16 @@ static void ev_radius_coa(struct ev_radius_t *ev)
pd->down_speed = pd->cur_tr->down_speed;
pd->up_speed = pd->cur_tr->up_speed;
- if (remove_limiter(ev->ses)) {
+ if (pd->idx && remove_limiter(ev->ses, pd->idx)) {
ev->res = -1;
return;
}
if (pd->down_speed > 0 || pd->up_speed > 0) {
- if (install_limiter(ev->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst)) {
+ if (!pd->idx)
+ pd->idx = alloc_idx(pd->ses->ifindex);
+
+ if (install_limiter(ev->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst, pd->idx)) {
ev->res= -1;
return;
} else {
@@ -386,8 +440,11 @@ static void ev_shaper(struct ev_shaper_t *ev)
pd->up_speed = up_speed;
}
+ if (!pd->idx)
+ pd->idx = alloc_idx(pd->ses->ifindex);
+
if (pd->down_speed > 0 && pd->up_speed > 0) {
- if (!install_limiter(ev->ses, down_speed, down_burst, up_speed, up_burst)) {
+ if (!install_limiter(ev->ses, down_speed, down_burst, up_speed, up_burst, pd->idx)) {
if (conf_verbose)
log_ppp_info2("shaper: installed shaper %i/%i (Kbit)\n", down_speed, up_speed);
}
@@ -423,8 +480,11 @@ static void ev_ppp_pre_up(struct ap_session *ses)
up_burst = pd->cur_tr->up_burst;
}
+ if (!pd->idx)
+ pd->idx = alloc_idx(ses->ifindex);
+
if (down_speed > 0 && up_speed > 0) {
- if (!install_limiter(ses, down_speed, down_burst, up_speed, up_burst)) {
+ if (!install_limiter(ses, down_speed, down_burst, up_speed, up_burst, pd->idx)) {
if (conf_verbose)
log_ppp_info2("shaper: installed shaper %i/%i (Kbit)\n", down_speed, up_speed);
}
@@ -437,13 +497,15 @@ static void ev_ppp_finishing(struct ap_session *ses)
if (pd) {
pthread_rwlock_wrlock(&shaper_lock);
+ if (pd->idx)
+ free_idx(pd->idx);
list_del(&pd->entry);
pthread_rwlock_unlock(&shaper_lock);
list_del(&pd->pd.entry);
if (pd->down_speed || pd->up_speed)
- remove_limiter(ses);
+ remove_limiter(ses, pd->idx);
if (__sync_sub_and_fetch(&pd->refs, 1) == 0) {
clear_tr_pd(pd);
@@ -465,16 +527,18 @@ static void shaper_change(struct shaper_pd_t *pd)
goto out;
if (pd->down_speed || pd->up_speed)
- remove_limiter(pd->ses);
+ remove_limiter(pd->ses, pd->idx);
+ else if (!pd->idx)
+ pd->idx = alloc_idx(pd->ses->ifindex);
if (pd->temp_down_speed || pd->temp_up_speed) {
pd->down_speed = pd->temp_down_speed;
pd->up_speed = pd->temp_up_speed;
- install_limiter(pd->ses, pd->temp_down_speed, 0, pd->temp_up_speed, 0);
+ install_limiter(pd->ses, pd->temp_down_speed, 0, pd->temp_up_speed, 0, pd->idx);
} else if (pd->cur_tr->down_speed || pd->cur_tr->up_speed) {
pd->down_speed = pd->cur_tr->down_speed;
pd->up_speed = pd->cur_tr->up_speed;
- install_limiter(pd->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst);
+ install_limiter(pd->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst, pd->idx);
} else {
pd->down_speed = 0;
pd->up_speed = 0;
@@ -561,12 +625,12 @@ static void shaper_restore(struct shaper_pd_t *pd)
if (!pd->ses || pd->ses->terminating)
goto out;
- remove_limiter(pd->ses);
+ remove_limiter(pd->ses, pd->idx);
if (pd->cur_tr) {
pd->down_speed = pd->cur_tr->down_speed;
pd->up_speed = pd->cur_tr->up_speed;
- install_limiter(pd->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst);
+ install_limiter(pd->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst, pd->idx);
} else {
pd->down_speed = 0;
pd->up_speed = 0;
@@ -666,13 +730,16 @@ static void update_shaper_tr(struct shaper_pd_t *pd)
if (pd->down_speed || pd->up_speed) {
if (pd->cur_tr && pd->down_speed == pd->cur_tr->down_speed && pd->up_speed == pd->cur_tr->up_speed)
goto out;
- remove_limiter(pd->ses);
+ remove_limiter(pd->ses, pd->idx);
}
if (pd->cur_tr && (pd->cur_tr->down_speed || pd->cur_tr->up_speed)) {
+ if (!pd->idx)
+ pd->idx = alloc_idx(pd->ses->ifindex);
+
pd->down_speed = pd->cur_tr->down_speed;
pd->up_speed = pd->cur_tr->up_speed;
- if (!install_limiter(pd->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst)) {
+ if (!install_limiter(pd->ses, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst, pd->idx)) {
if (conf_verbose)
log_ppp_info2("shaper: changed shaper %i/%i (Kbit)\n", pd->cur_tr->down_speed, pd->cur_tr->up_speed);
}
@@ -997,6 +1064,10 @@ static void init(void)
tc_core_init();
+ idx_map = mmap(NULL, MAX_IDX/8, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ memset(idx_map, 0xff, MAX_IDX/8);
+ idx_map[0] &= ~3;
+
opt = conf_get_opt("shaper", "ifb");
if (opt && init_ifb(opt))
_exit(0);
diff --git a/accel-pppd/shaper/shaper.h b/accel-pppd/shaper/shaper.h
index 87cf45f..1b1e885 100644
--- a/accel-pppd/shaper/shaper.h
+++ b/accel-pppd/shaper/shaper.h
@@ -45,8 +45,8 @@ extern int conf_lq_arg4;
extern int conf_lq_arg5;
extern int conf_lq_arg6;
-int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst);
-int remove_limiter(struct ap_session *ses);
+int install_limiter(struct ap_session *ses, int down_speed, int down_burst, int up_speed, int up_burst, int idx);
+int remove_limiter(struct ap_session *ses, int idx);
int install_leaf_qdisc(struct rtnl_handle *rth, int ifindex, int parent, int handle);
int init_ifb(const char *);