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