In this section an example of a Python script is described that enables the activation or deactivation of a subscriber service.
In the example, it is assumed that only a single subscriber service is activated or deactivated per RADIUS message (no tagged VSAs are used) and that only a single Alc-Sub-Serv-Activate or Alc-Sub-Serv-Deactivate VSA is present (no concatenation of VSAs is required).
To change the upstream root arbiter rate and downstream aggregate rate bandwidth of an IPoE session, send the following parameters in the subscriber service activate VSA:
rate-limit;<upstream_bw_in_kbps>;<downstream_bw_in_kbps>
During the bandwidth change, the traffic should be accounted for in a separate accounting session.
To import the required modules in the Python script:
# Python - imports
import struct
from alc import radius
from alc import sub_svc
The alc.radius module provides the API access to the RADIUS VSAs in Access-Accept and CoA messages.
The alc.sub_svc module allows the API to activate and deactivate subscriber services.
The struct module is a Python module used in the example to convert data obtained from the RADIUS API as a string into Python integer values.
The following constants are used in the script:
# Python - constants
# VSA vendor ID
ALC = 6527
# ALC Radius VSA
SUB_SERVICE_ACTIVATE = 151
SUB_SERVICE_DEACTIVATE = 152
SUB_SERVICE_ACCT_STATS_TYPE = 153
SUB_SERVICE_ACCT_INTERIM_IVL = 154
The main flow in a subscriber service Python script is to first process the subscriber service deactivations, followed by the subscriber service activations. Optionally, the subscriber service-specific VSAs can be removed from the RADIUS message as they are not required for further processing in the SR OS:
# Python - main()
deactivate_services()
activate_services()
radius.attributes.clearVSA(ALC, SUB_SERVICE_ACTIVATE)
radius.attributes.clearVSA(ALC, SUB_SERVICE_DEACTIVATE)
radius.attributes.clearVSA(ALC, SUB_SERVICE_ACCT_STATS_TYPE)
radius.attributes.clearVSA(ALC, SUB_SERVICE_ACCT_INTERIM_IVL)
The function to deactivate a subscriber service executes the following steps:
checks if an Alc-Sub-Serv-Deactivate VSA [26-6527-152] is present
if present:
builds the subscriber service data structure. For a subscriber service deactivation, only the subscriber service instance name is required.
commits the subscriber service deactivation
# Python - deactivate_services()
def deactivate_services():
value = radius.attributes.getVSA(ALC, SUB_SERVICE_DEACTIVATE)
if value != '':
service = []
sub_svc.add_to_service(service, sub_svc.name, value);
sub_svc.add_to_service(service, sub_svc.operation, sub_svc.operation_del);
sub_svc.commit_service(service)
The function to activate a subscriber service executes the following steps:
checks if an Alc-Sub-Serv-Activate VSA [26-6527-151] is present
if present:
separates the parameters in the attribute value with a semicolon as the delimiter. The parameters are the subscriber service type, the upstream bandwidth in kb/s, and the downstream bandwidth in kb/s.
If the subscriber service type is rate-limit, builds the subscriber service data structure:
specifies that the service is added (activate)
adds the complete attribute value as the subscriber service instance name. This name should also be used to deactivate the subscriber service.
sets the subscriber service type and conflict action. With the conflict action set to ‟keep new”, if a new subscriber service of the same type is activated, the old one is deactivated first.
configures the upstream and downstream bandwidth with a QoS override on the ingress root arbiter and egress aggregate rate
If the subscriber service type is something else (an unknown service type), a warning is printed for debugging purposes. No action is performed in this case.
If an Alc-Sub-Serv-Acct-Stats-Type VSA [26-6527-153] is present, adds the corresponding stats-type to the subscriber service data structure. The function also checks whether a Alc-Sub-Acct-Serv-Interim-Ivl VSA [26-6527-154] is present and adds the interval to the subscriber service data structure.
Both the stats-type and interim interval must be specified as integers in the subscriber service data structure. As the RADIUS API returns an octet string, a conversion is required. The struct.unpack() function is used for this purpose.
commits the subscriber service activation
# Python - activate_services()
def activate_services():
# Subscriber Service Activate VSA
value = radius.attributes.getVSA(ALC, SUB_SERVICE_ACTIVATE)
if value != '':
values = value.split(';')
if values[0] == "rate-limit":
service = []
sub_svc.add_to_service(service, sub_svc.operation, sub_svc.operation_add);
sub_svc.add_to_service(service, sub_svc.name, value);
sub_svc.add_to_service(service, sub_svc.type, 'rate-limit')
sub_svc.add_to_service(service, sub_svc.type_conflict_action, sub_svc.type_con
flict_action_keep_new)
sub_svc.add_to_service(service, sub_svc.qos_override, 'i:a:root:rate=' +
values[1])
sub_svc.add_to_service(service, sub_svc.qos_override, 'e:r:rate=' + values[2])
else:
print "WARNING - Unknown service type :", values[0]
return
# Subscriber Service Accounting VSA
stats_type = radius.attributes.getVSA(ALC, SUB_SERVICE_ACCT_STATS_TYPE)
if stats_type != '':
sub_svc.add_to_service(service, sub_svc.acct_stats_type, struct.unpack("!I", s
tats_type)[0]);
interval = radius.attributes.getVSA(ALC, SUB_SERVICE_ACCT_INTERIM_IVL)
if interval != '':
sub_svc.add_to_service(service, sub_svc.acct_interval, struct.unpack("!I", i
nterval)[0]);
# Activate the Subscriber Service
sub_svc.commit_service(service)
The result of the sub_svc.commit_service() function is an Alc-Sub-Serv-Internal VSA [26-6527-155] that contains the required data for the SR OS to activate the corresponding subscriber services.