Dynamic update of rate-limit
Ali Arslan
e066377 at yahoo.com
Wed Jul 10 00:53:04 CEST 2019
Hello,
To update users rate-limits dynamically i have defined following custom attributes in dictionary file
ATTRIBUTE Subscriber-NAS-Vendor 3050 string
ATTRIBUTE Subscriber-Total-Bytes 3051 integer64
ATTRIBUTE Subscriber-Quota 3052 integer64
ATTRIBUTE Fair-Usage-Rate 3053 integer
and written following unlang codes in accounting section:
# Rate Policy for unlimited, fair usage and limeted accounts
update control {
Subscriber-NAS-Vendor = "%{sql: SELECT nas_vendor FROM radcheck WHERE username='%{User-Name}' AND attribute = 'Cleartext-Password' limit 1}"
Subscriber-Quota = "%{sql:SELECT IFNULL(quota, 0) FROM radcheck WHERE username='%{User-Name}' AND attribute = 'Cleartext-Password' limit 1}"
}
if (&control:Subscriber-Quota > 0) {
update control {
Subscriber-Total-Bytes = "%{sql:SELECT IFNULL(SUM(IFNULL(acctinputoctets, 0) + IFNULL(acctoutputoctets, 0)), 0) FROM radacct WHERE username='%{User-Name}'AND acctstarttime\
>= DATE_SUB(LAST_DAY(NOW()), INTERVAL DAY(LAST_DAY(NOW()))-1 DAY)}"
Fair-Usage-Rate = "%{sql:SELECT IFNULL(fairusage_rate, 0) FROM radcheck WHERE username='%{User-Name}' AND attribute = 'Cleartext-Password' limit 1}"
}
}
# over qouta fair usage acoount
if (&control:Subscriber-Quota > 0 && &control:Fair-Usage-Rate > 0 && &control:Subscriber-Total-Bytes > &control:Subscriber-Quota) {
switch "%{&control:Subscriber-NAS-Vendor}" {
case "Mikrotik" {
update reply {
&Mikrotik-Rate-Limit = "%{sql:SELECT GetRate('%{User-Name}', 'fairusage')}"
}
}
case "Cisco" {
update reply {
&Cisco-Avpair = "%{sql:SELECT GetRate('%{User-Name}', 'fairusage')}"
&Cisco-Avpair += "%{sql:SELECT GetRate('%{User-Name}', 'upload')}"
}
}
}
}
# over quota limited account
elsif (&control:Subscriber-Quota > 0 && &control:Fair-Usage-Rate == 0 && &control:Subscriber-Total-Bytes > &control:Subscriber-Quota) {
update disconnect {
&User-Name := "%{User-Name}"
}
}
# unlimited and other accounts under quota
else {
switch "%{&control:Subscriber-NAS-Vendor}" {
case "Mikrotik" {
update reply {
# upload and download strings are equal for Mikrotik (Uk/Dk)
&Mikrotik-Rate-Limit = "%{sql:SELECT GetRate('%{User-Name}', 'download')}"
}
}
case "Cisco" {
update reply {
&Cisco-Avpair = "%{sql:SELECT GetRate('%{User-Name}', 'download')}"
&Cisco-Avpair += "%{sql:SELECT GetRate('%{User-Name}', 'upload')}"
}
}
}
}
if i test it with a user for Mikrotik nas for which GetRate sql function returns 2048k/16324k rate string the relevant part in freeradius debug output is:
Executing select query: SELECT TOP 1 nas_vendor FROM radcheck WHERE username='aaa at dinler' AND attribute = 'Cleartext-Password'
rlm_sql (sql): Released connection (5)
(1) EXPAND %{sql: SELECT TOP 1 nas_vendor FROM radcheck WHERE username='%{User-Name}' AND attribute = 'Cleartext-Password'}
(1) --> Mikrotik
(1) Subscriber-NAS-Vendor = Mikrotik
(1) EXPAND %{User-Name}
(1) --> aaa at dinler
(1) SQL-User-Name set to 'aaa at dinler'
rlm_sql (sql): Reserved connection (1)
(1) Executing select query: SELECT TOP 1 ISNULL(quota, 0) FROM radcheck WHERE username='aaa at dinler' AND attribute = 'Cleartext-Password'
rlm_sql (sql): Released connection (1)
(1) EXPAND %{sql:SELECT TOP 1 ISNULL(quota, 0) FROM radcheck WHERE username='%{User-Name}' AND attribute = 'Cleartext-Password'}
(1) --> 0
(1) Subscriber-Quota = 0
(1) } # update control = noop
(1) if (&control:Subscriber-Quota > 0) {
(1) if (&control:Subscriber-Quota > 0) -> FALSE
(1) if (&control:Subscriber-Quota > 0 && &control:Fair-Usage-Rate > 0 && &control:Subscriber-Total-Bytes > &control:Subscriber-Quota) {
(1) if (&control:Subscriber-Quota > 0 && &control:Fair-Usage-Rate > 0 && &control:Subscriber-Total-Bytes > &control:Subscriber-Quota) -> FALSE
(1) elsif (&control:Subscriber-Quota > 0 && &control:Fair-Usage-Rate == 0 && &control:Subscriber-Total-Bytes > &control:Subscriber-Quota) {
(1) elsif (&control:Subscriber-Quota > 0 && &control:Fair-Usage-Rate == 0 && &control:Subscriber-Total-Bytes > &control:Subscriber-Quota) -> FALSE
(1) else {
(1) switch %{&control:Subscriber-NAS-Vendor} {
(1) case Mikrotik {
(1) update reply {
(1) EXPAND %{User-Name}
(1) --> aaa at dinler
(1) SQL-User-Name set to 'aaa at dinler'
rlm_sql (sql): Reserved connection (2)
(1) Executing select query: SELECT dbo.GetRate('aaa at dinler', 'download')
rlm_sql (sql): Released connection (2)
(1) EXPAND %{sql:SELECT dbo.GetRate('%{User-Name}', 'download')}
(1) --> 2048k/16324k
(1) &Mikrotik-Rate-Limit = 2048k/16324k
(1) } # update reply = noop
(1) } # case Mikrotik = noop
(1) } # switch %{&control:Subscriber-NAS-Vendor} = noop
(1) } # else = noop
(1) [exec] = noop
(1) attr_filter.accounting_response: EXPAND %{User-Name}
(1) attr_filter.accounting_response: --> aaa at dinler
(1) attr_filter.accounting_response: Matched entry DEFAULT at line 12
(1) [attr_filter.accounting_response] = updated
(1) } # accounting = updated
(1) Sent Accounting-Response Id 1 from 127.0.0.1:1813 to 127.0.0.1:61732 length 0
(1) Mikrotik-Rate-Limit = "2048k/16324k"
(1) Finished request
all look fine, but the reply message
Mikrotik-Rate-Limit = "2048k/16324k"
is not conformed.
But if i set Mikrotik-Rate-Limit = "2048k/16324k" in radreply table atleast upload rate is obeyed.
Do i update reply in wrong place, or doing some other things wrong?
Thanks.
More information about the Freeradius-Users
mailing list